You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by "stevedlawrence (via GitHub)" <gi...@apache.org> on 2023/08/18 12:31:27 UTC
[GitHub] [daffodil] stevedlawrence opened a new pull request, #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
stevedlawrence opened a new pull request, #1070:
URL: https://github.com/apache/daffodil/pull/1070
This removes the dfdlx:inputTypeCalc and dfdlx:outputTypeCalc properties and DPath functions. This allows for removal of a number of related member variables and functions used only by the expression type calc functions. For example, the typeCalcMap is only used by the functions to lookup a calculator by QName at runtime. All type calculators are known statically at compile time, so everything related to runtime type calculator maps goes away.
Also does some minor refactoring:
- Moves code around so similar logic is all in one place or removes conditionals
- Changes a tuple where only element has a meaningful value to an Either so we enforce that restriction
- Fixes typo in IdentityTypeCalc name
- Changes some error messages so they are a bit more less developer centric
DAFFODIL-2211
----
Note that this is only part of of DAFFODIL-2211. I'm making this a separate PR so it's more clear which parts are about removing input/outputValueCalc and which parts are about updating the diagnostics. It also means if we ever want to bring back typeValueCalc, we can just revert this PR without undoing the diagnostic changes
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] tuxji commented on a diff in pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "tuxji (via GitHub)" <gi...@apache.org>.
tuxji commented on code in PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#discussion_r1298603950
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -40,116 +35,72 @@ abstract class TypeCalculator(val srcType: NodeInfo.Kind, val dstType: NodeInfo.
extends Serializable {
Review Comment:
I would also add a scaladoc comment to this class giving an overview of what type calculations are used for in Daffodil schema compilation.
##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SimpleTypes.scala:
##########
@@ -312,40 +308,49 @@ abstract class SimpleTypeDefBase(xml: Node, lexicalParent: SchemaComponent)
}
}
- lazy val optInputTypeCalc = findPropertyOption("inputTypeCalc", expressionAllowed = true)
- lazy val optOutputTypeCalc = findPropertyOption("outputTypeCalc", expressionAllowed = true)
-
lazy val optTypeCalculator: Option[TypeCalculator] = LV('optTypeCalculator) {
Review Comment:
I haven't read about type calculations before your PR. Please add a comment here explaining what a type calculator does for DFDL schema compilation. I see 5 uses of optTypeCalculator in my checkout and 2 uses left in your branch, so I wonder what prevented you from simply removing everything to do with type calculations (although I assume they have something to do with reptypes).
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] mbeckerle commented on a diff in pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "mbeckerle (via GitHub)" <gi...@apache.org>.
mbeckerle commented on code in PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#discussion_r1303615295
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -223,159 +186,34 @@ class KeysetValueTypeCalculatorUnordered(
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
valueMap.get(x) match {
- case Some(a) => (a, Maybe.Nope)
- case None =>
- (DataValue.NoValue, One(s"Value ${x} not found in enumeration dfdlx:repValues"))
+ case Some(a) => Right(a)
+ case None => Left(s"Value ${x} not found in enumeration dfdlx:repValues")
}
}
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
unparseMap.get(x) match {
- case Some(v) => (v, Maybe.Nope)
- case None => (DataValue.NoValue, One(s"Value ${x} not found in enumeration"))
+ case Some(v) => Right(v)
+ case None => Left(s"Value ${x} not found in enumeration")
}
}
}
-class ExpressionTypeCalculator(
- private val maybeInputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- private val maybeOutputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- srcType: NodeInfo.Kind,
- dstType: NodeInfo.Kind,
-) extends TypeCalculator(srcType, dstType) {
-
- /*
- * objects with Delay arguments for functional programming construction of
- * cyclic graphs, need a way to force the delays, resulting in an ordinary
- * (though cyclic) data structure.
- */
- final override def initialize(): Unit = {
- super.initialize()
- maybeInputTypeCalc
- maybeOutputTypeCalc
- }
-
- override def supportsParse = maybeInputTypeCalc.isDefined
- override def supportsUnparse = maybeOutputTypeCalc.isDefined
-
- /*
- * Compiling DPath expressions may need to evaluate typeCalculators in order to lookup their srcType and dstType.
- * To prevent circular dependencies, this means that the underlying expressions must be lazy.
- *
- * Since these fields must be lazy, we cannot use them to determine supportsParse or supportUnparse
- */
- lazy val maybeInputTypeCalc = maybeInputTypeCalcDelay.value
- lazy val maybeOutputTypeCalc = maybeOutputTypeCalcDelay.value
-
- // The class TypeValueCalc will verify that supports(Un)Parse is true when nessasary
- // Therefore, if we ever call the below functions, we know that the relevent Maybe object is defined.
-
- // TODO, pass x into DPath state
-
+class IdentityTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "inputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "outputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
-
- override def inputTypeCalcParse(
- state: PState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- val ans = Maybe(maybeInputTypeCalc.get.evaluate(state))
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- if (ans.isDefined) {
- DataValue.unsafeFromAnyRef(ans.get)
- } else {
- DataValue.NoValue;
- }
- }
- override def outputTypeCalcUnparse(
- state: UState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- val ans = maybeOutputTypeCalc.get.evaluate(state)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- DataValue.unsafeFromAnyRef(ans)
- }
-
- override def inputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- maybeInputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
-
- }
- override def outputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- maybeOutputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- }
-}
-
-class IdentifyTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
- override def inputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
- override def outputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
}
class UnionTypeCalculator(
Review Comment:
That said, are we sure we're not introducing yet another backward incompatibility.. We need to look at the complex schemas that were using inputTypeCalc et al, and see if they're using these union features.
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] mbeckerle commented on a diff in pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "mbeckerle (via GitHub)" <gi...@apache.org>.
mbeckerle commented on code in PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#discussion_r1298825577
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -223,159 +186,34 @@ class KeysetValueTypeCalculatorUnordered(
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
valueMap.get(x) match {
- case Some(a) => (a, Maybe.Nope)
- case None =>
- (DataValue.NoValue, One(s"Value ${x} not found in enumeration dfdlx:repValues"))
+ case Some(a) => Right(a)
+ case None => Left(s"Value ${x} not found in enumeration dfdlx:repValues")
}
}
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
unparseMap.get(x) match {
- case Some(v) => (v, Maybe.Nope)
- case None => (DataValue.NoValue, One(s"Value ${x} not found in enumeration"))
+ case Some(v) => Right(v)
+ case None => Left(s"Value ${x} not found in enumeration")
}
}
}
-class ExpressionTypeCalculator(
- private val maybeInputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- private val maybeOutputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- srcType: NodeInfo.Kind,
- dstType: NodeInfo.Kind,
-) extends TypeCalculator(srcType, dstType) {
-
- /*
- * objects with Delay arguments for functional programming construction of
- * cyclic graphs, need a way to force the delays, resulting in an ordinary
- * (though cyclic) data structure.
- */
- final override def initialize(): Unit = {
- super.initialize()
- maybeInputTypeCalc
- maybeOutputTypeCalc
- }
-
- override def supportsParse = maybeInputTypeCalc.isDefined
- override def supportsUnparse = maybeOutputTypeCalc.isDefined
-
- /*
- * Compiling DPath expressions may need to evaluate typeCalculators in order to lookup their srcType and dstType.
- * To prevent circular dependencies, this means that the underlying expressions must be lazy.
- *
- * Since these fields must be lazy, we cannot use them to determine supportsParse or supportUnparse
- */
- lazy val maybeInputTypeCalc = maybeInputTypeCalcDelay.value
- lazy val maybeOutputTypeCalc = maybeOutputTypeCalcDelay.value
-
- // The class TypeValueCalc will verify that supports(Un)Parse is true when nessasary
- // Therefore, if we ever call the below functions, we know that the relevent Maybe object is defined.
-
- // TODO, pass x into DPath state
-
+class IdentityTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
Review Comment:
Curious as to why we still need this. For unit tests?
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -21,135 +21,98 @@ import scala.collection.immutable.HashMap
import scala.collection.immutable.HashSet
import org.apache.daffodil.lib.exceptions.Assert
-import org.apache.daffodil.lib.util.Delay
import org.apache.daffodil.lib.util.Maybe
-import org.apache.daffodil.lib.util.Maybe.One
import org.apache.daffodil.lib.util.Numbers
-import org.apache.daffodil.lib.xml.QNameBase
-import org.apache.daffodil.runtime1.dpath.DState
import org.apache.daffodil.runtime1.dpath.NodeInfo
-import org.apache.daffodil.runtime1.dsom.CompiledExpression
import org.apache.daffodil.runtime1.infoset.DataValue
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitive
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitiveNullable
import org.apache.daffodil.runtime1.processors.parsers.PState
import org.apache.daffodil.runtime1.processors.parsers.ParseError
import org.apache.daffodil.runtime1.processors.unparsers.UState
+/**
+ * A TypeCalculator is a class that performs some kind of conversion from one DataValuePrimitive
+ * to another DataValuePrimitive. In general, this is done to convert a parsed physical
+ * representation from the data to a logical representation that goes in the infoset, and
+ * reverse on unparse. The former is done in the inputTypeCalc functions, and the latter in the
+ * outputTypeCalc functions. Generally the conversion is to a different type (e.g. xs:int to
+ * xs:string), but this need not be the case.
Review Comment:
Do we in fact still support other than int to/from string?
Possibly this class/framework does, but other aspects of these extensions do not?
If this is only used (and tested) for int to/from string, we should not lay claim to other conversions.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -21,135 +21,98 @@ import scala.collection.immutable.HashMap
import scala.collection.immutable.HashSet
import org.apache.daffodil.lib.exceptions.Assert
-import org.apache.daffodil.lib.util.Delay
import org.apache.daffodil.lib.util.Maybe
-import org.apache.daffodil.lib.util.Maybe.One
import org.apache.daffodil.lib.util.Numbers
-import org.apache.daffodil.lib.xml.QNameBase
-import org.apache.daffodil.runtime1.dpath.DState
import org.apache.daffodil.runtime1.dpath.NodeInfo
-import org.apache.daffodil.runtime1.dsom.CompiledExpression
import org.apache.daffodil.runtime1.infoset.DataValue
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitive
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitiveNullable
import org.apache.daffodil.runtime1.processors.parsers.PState
import org.apache.daffodil.runtime1.processors.parsers.ParseError
import org.apache.daffodil.runtime1.processors.unparsers.UState
+/**
+ * A TypeCalculator is a class that performs some kind of conversion from one DataValuePrimitive
+ * to another DataValuePrimitive. In general, this is done to convert a parsed physical
+ * representation from the data to a logical representation that goes in the infoset, and
+ * reverse on unparse. The former is done in the inputTypeCalc functions, and the latter in the
+ * outputTypeCalc functions. Generally the conversion is to a different type (e.g. xs:int to
+ * xs:string), but this need not be the case.
+ *
+ * The different TypeCalculator implementations allow for different conversions based on
+ * different properties provided in the schema (e.g. repType, enumerations, unions, repValues,
Review Comment:
I'm not recollecting what we do with unions and this stuff. That may be only the floating type calc functions that have been removed.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -223,159 +186,34 @@ class KeysetValueTypeCalculatorUnordered(
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
valueMap.get(x) match {
- case Some(a) => (a, Maybe.Nope)
- case None =>
- (DataValue.NoValue, One(s"Value ${x} not found in enumeration dfdlx:repValues"))
+ case Some(a) => Right(a)
+ case None => Left(s"Value ${x} not found in enumeration dfdlx:repValues")
}
}
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
unparseMap.get(x) match {
- case Some(v) => (v, Maybe.Nope)
- case None => (DataValue.NoValue, One(s"Value ${x} not found in enumeration"))
+ case Some(v) => Right(v)
+ case None => Left(s"Value ${x} not found in enumeration")
}
}
}
-class ExpressionTypeCalculator(
- private val maybeInputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- private val maybeOutputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- srcType: NodeInfo.Kind,
- dstType: NodeInfo.Kind,
-) extends TypeCalculator(srcType, dstType) {
-
- /*
- * objects with Delay arguments for functional programming construction of
- * cyclic graphs, need a way to force the delays, resulting in an ordinary
- * (though cyclic) data structure.
- */
- final override def initialize(): Unit = {
- super.initialize()
- maybeInputTypeCalc
- maybeOutputTypeCalc
- }
-
- override def supportsParse = maybeInputTypeCalc.isDefined
- override def supportsUnparse = maybeOutputTypeCalc.isDefined
-
- /*
- * Compiling DPath expressions may need to evaluate typeCalculators in order to lookup their srcType and dstType.
- * To prevent circular dependencies, this means that the underlying expressions must be lazy.
- *
- * Since these fields must be lazy, we cannot use them to determine supportsParse or supportUnparse
- */
- lazy val maybeInputTypeCalc = maybeInputTypeCalcDelay.value
- lazy val maybeOutputTypeCalc = maybeOutputTypeCalcDelay.value
-
- // The class TypeValueCalc will verify that supports(Un)Parse is true when nessasary
- // Therefore, if we ever call the below functions, we know that the relevent Maybe object is defined.
-
- // TODO, pass x into DPath state
-
+class IdentityTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "inputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "outputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
-
- override def inputTypeCalcParse(
- state: PState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- val ans = Maybe(maybeInputTypeCalc.get.evaluate(state))
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- if (ans.isDefined) {
- DataValue.unsafeFromAnyRef(ans.get)
- } else {
- DataValue.NoValue;
- }
- }
- override def outputTypeCalcUnparse(
- state: UState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- val ans = maybeOutputTypeCalc.get.evaluate(state)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- DataValue.unsafeFromAnyRef(ans)
- }
-
- override def inputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- maybeInputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
-
- }
- override def outputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- maybeOutputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- }
-}
-
-class IdentifyTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
- override def inputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
- override def outputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
}
class UnionTypeCalculator(
Review Comment:
I suspect this might be able to go away. I'm not understanding any feature of unions. I mean do we allow simple type unions as a repType or can one combine enums with a rep type using unions?
This change set is complex enough, so if you want to put off further investigation of this I'm good with that.
And I also could be entirely mistaken and this stuff may need to be here.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -183,9 +146,9 @@ class KeysetValueTypeCalculatorOrdered(
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
Review Comment:
Ah, so you also changed this return type from tuple to Either. That's cleaner also.
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] stevedlawrence commented on pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "stevedlawrence (via GitHub)" <gi...@apache.org>.
stevedlawrence commented on PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#issuecomment-1684103317
To do before merged, this needs a `Deprecation/Compatibility` section in the commit message to go in the release notes.
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] stevedlawrence commented on a diff in pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "stevedlawrence (via GitHub)" <gi...@apache.org>.
stevedlawrence commented on code in PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#discussion_r1298643965
##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SimpleTypes.scala:
##########
@@ -312,40 +308,49 @@ abstract class SimpleTypeDefBase(xml: Node, lexicalParent: SchemaComponent)
}
}
- lazy val optInputTypeCalc = findPropertyOption("inputTypeCalc", expressionAllowed = true)
- lazy val optOutputTypeCalc = findPropertyOption("outputTypeCalc", expressionAllowed = true)
-
lazy val optTypeCalculator: Option[TypeCalculator] = LV('optTypeCalculator) {
Review Comment:
Will do, I had to learn about type calculators too so this would definitely be useful. Quickly, type calculators are used to convert a parsed value (based on the repType) to a value that actually ends up in the infoset. There are different type calculators for supporting conversions based on enumerations and unions, and previously expressions, which is now removed.
So a parser actually parses the data (based on the repType), and the type calculator converts that parsed value to something else (based on the enumeration/union), usually with a different type, and that ends up in the infoset.
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] stevedlawrence merged pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "stevedlawrence (via GitHub)" <gi...@apache.org>.
stevedlawrence merged PR #1070:
URL: https://github.com/apache/daffodil/pull/1070
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] stevedlawrence commented on a diff in pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "stevedlawrence (via GitHub)" <gi...@apache.org>.
stevedlawrence commented on code in PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#discussion_r1304229375
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -223,159 +186,34 @@ class KeysetValueTypeCalculatorUnordered(
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
valueMap.get(x) match {
- case Some(a) => (a, Maybe.Nope)
- case None =>
- (DataValue.NoValue, One(s"Value ${x} not found in enumeration dfdlx:repValues"))
+ case Some(a) => Right(a)
+ case None => Left(s"Value ${x} not found in enumeration dfdlx:repValues")
}
}
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
unparseMap.get(x) match {
- case Some(v) => (v, Maybe.Nope)
- case None => (DataValue.NoValue, One(s"Value ${x} not found in enumeration"))
+ case Some(v) => Right(v)
+ case None => Left(s"Value ${x} not found in enumeration")
}
}
}
-class ExpressionTypeCalculator(
- private val maybeInputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- private val maybeOutputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- srcType: NodeInfo.Kind,
- dstType: NodeInfo.Kind,
-) extends TypeCalculator(srcType, dstType) {
-
- /*
- * objects with Delay arguments for functional programming construction of
- * cyclic graphs, need a way to force the delays, resulting in an ordinary
- * (though cyclic) data structure.
- */
- final override def initialize(): Unit = {
- super.initialize()
- maybeInputTypeCalc
- maybeOutputTypeCalc
- }
-
- override def supportsParse = maybeInputTypeCalc.isDefined
- override def supportsUnparse = maybeOutputTypeCalc.isDefined
-
- /*
- * Compiling DPath expressions may need to evaluate typeCalculators in order to lookup their srcType and dstType.
- * To prevent circular dependencies, this means that the underlying expressions must be lazy.
- *
- * Since these fields must be lazy, we cannot use them to determine supportsParse or supportUnparse
- */
- lazy val maybeInputTypeCalc = maybeInputTypeCalcDelay.value
- lazy val maybeOutputTypeCalc = maybeOutputTypeCalcDelay.value
-
- // The class TypeValueCalc will verify that supports(Un)Parse is true when nessasary
- // Therefore, if we ever call the below functions, we know that the relevent Maybe object is defined.
-
- // TODO, pass x into DPath state
-
+class IdentityTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "inputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "outputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
-
- override def inputTypeCalcParse(
- state: PState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- val ans = Maybe(maybeInputTypeCalc.get.evaluate(state))
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- if (ans.isDefined) {
- DataValue.unsafeFromAnyRef(ans.get)
- } else {
- DataValue.NoValue;
- }
- }
- override def outputTypeCalcUnparse(
- state: UState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- val ans = maybeOutputTypeCalc.get.evaluate(state)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- DataValue.unsafeFromAnyRef(ans)
- }
-
- override def inputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- maybeInputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
-
- }
- override def outputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- maybeOutputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- }
-}
-
-class IdentifyTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
- override def inputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
- override def outputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
}
class UnionTypeCalculator(
Review Comment:
I've grepped through our regression suite, and of the handful of schemas that use `xs:union`s, none of those unions or the simple types they reference use `repType`. We do use unions, but it looks like they are used to combine various restrictions.
So I don't think we would break anything by removing repType union support. I'll remove union repType support as a separate PR and test the regression suite first to make sure there are no breakages.
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] stevedlawrence commented on a diff in pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "stevedlawrence (via GitHub)" <gi...@apache.org>.
stevedlawrence commented on code in PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#discussion_r1299973051
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -21,135 +21,98 @@ import scala.collection.immutable.HashMap
import scala.collection.immutable.HashSet
import org.apache.daffodil.lib.exceptions.Assert
-import org.apache.daffodil.lib.util.Delay
import org.apache.daffodil.lib.util.Maybe
-import org.apache.daffodil.lib.util.Maybe.One
import org.apache.daffodil.lib.util.Numbers
-import org.apache.daffodil.lib.xml.QNameBase
-import org.apache.daffodil.runtime1.dpath.DState
import org.apache.daffodil.runtime1.dpath.NodeInfo
-import org.apache.daffodil.runtime1.dsom.CompiledExpression
import org.apache.daffodil.runtime1.infoset.DataValue
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitive
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitiveNullable
import org.apache.daffodil.runtime1.processors.parsers.PState
import org.apache.daffodil.runtime1.processors.parsers.ParseError
import org.apache.daffodil.runtime1.processors.unparsers.UState
+/**
+ * A TypeCalculator is a class that performs some kind of conversion from one DataValuePrimitive
+ * to another DataValuePrimitive. In general, this is done to convert a parsed physical
+ * representation from the data to a logical representation that goes in the infoset, and
+ * reverse on unparse. The former is done in the inputTypeCalc functions, and the latter in the
+ * outputTypeCalc functions. Generally the conversion is to a different type (e.g. xs:int to
+ * xs:string), but this need not be the case.
Review Comment:
I think we support all int-like types to string. I think only decimal, float, double, calendar, etc. are not supported. We do also support string to string using the identity type calculator, which was untested but I did add a test for. I'm not sure what the use case for this was, but the logic was there.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -223,159 +186,34 @@ class KeysetValueTypeCalculatorUnordered(
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
valueMap.get(x) match {
- case Some(a) => (a, Maybe.Nope)
- case None =>
- (DataValue.NoValue, One(s"Value ${x} not found in enumeration dfdlx:repValues"))
+ case Some(a) => Right(a)
+ case None => Left(s"Value ${x} not found in enumeration dfdlx:repValues")
}
}
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
unparseMap.get(x) match {
- case Some(v) => (v, Maybe.Nope)
- case None => (DataValue.NoValue, One(s"Value ${x} not found in enumeration"))
+ case Some(v) => Right(v)
+ case None => Left(s"Value ${x} not found in enumeration")
}
}
}
-class ExpressionTypeCalculator(
- private val maybeInputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- private val maybeOutputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- srcType: NodeInfo.Kind,
- dstType: NodeInfo.Kind,
-) extends TypeCalculator(srcType, dstType) {
-
- /*
- * objects with Delay arguments for functional programming construction of
- * cyclic graphs, need a way to force the delays, resulting in an ordinary
- * (though cyclic) data structure.
- */
- final override def initialize(): Unit = {
- super.initialize()
- maybeInputTypeCalc
- maybeOutputTypeCalc
- }
-
- override def supportsParse = maybeInputTypeCalc.isDefined
- override def supportsUnparse = maybeOutputTypeCalc.isDefined
-
- /*
- * Compiling DPath expressions may need to evaluate typeCalculators in order to lookup their srcType and dstType.
- * To prevent circular dependencies, this means that the underlying expressions must be lazy.
- *
- * Since these fields must be lazy, we cannot use them to determine supportsParse or supportUnparse
- */
- lazy val maybeInputTypeCalc = maybeInputTypeCalcDelay.value
- lazy val maybeOutputTypeCalc = maybeOutputTypeCalcDelay.value
-
- // The class TypeValueCalc will verify that supports(Un)Parse is true when nessasary
- // Therefore, if we ever call the below functions, we know that the relevent Maybe object is defined.
-
- // TODO, pass x into DPath state
-
+class IdentityTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "inputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "outputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
-
- override def inputTypeCalcParse(
- state: PState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- val ans = Maybe(maybeInputTypeCalc.get.evaluate(state))
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- if (ans.isDefined) {
- DataValue.unsafeFromAnyRef(ans.get)
- } else {
- DataValue.NoValue;
- }
- }
- override def outputTypeCalcUnparse(
- state: UState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- val ans = maybeOutputTypeCalc.get.evaluate(state)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- DataValue.unsafeFromAnyRef(ans)
- }
-
- override def inputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- maybeInputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
-
- }
- override def outputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- maybeOutputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- }
-}
-
-class IdentifyTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
- override def inputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
- override def outputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
}
class UnionTypeCalculator(
Review Comment:
> Do we allow simple type unions as a repType or can one combine enums with a rep type using unions?
We allow a simple type to be a union of other simple types which can have repTypes defined. We only have one tdml test for it (and a couple of unit tests) so I'm not sure how heavily it's tested or used, but it seems to work.
Daffodil also supports unions in general (see union.tdml), so maybe it was added for that reason?
If we think this repType unions is unnecessary I can remove it to, I think it would be pretty straightforward and I'd rather do it now while it's all fresh in my memory. But I can do it in a separate PR if that's preferred.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -21,135 +21,98 @@ import scala.collection.immutable.HashMap
import scala.collection.immutable.HashSet
import org.apache.daffodil.lib.exceptions.Assert
-import org.apache.daffodil.lib.util.Delay
import org.apache.daffodil.lib.util.Maybe
-import org.apache.daffodil.lib.util.Maybe.One
import org.apache.daffodil.lib.util.Numbers
-import org.apache.daffodil.lib.xml.QNameBase
-import org.apache.daffodil.runtime1.dpath.DState
import org.apache.daffodil.runtime1.dpath.NodeInfo
-import org.apache.daffodil.runtime1.dsom.CompiledExpression
import org.apache.daffodil.runtime1.infoset.DataValue
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitive
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitiveNullable
import org.apache.daffodil.runtime1.processors.parsers.PState
import org.apache.daffodil.runtime1.processors.parsers.ParseError
import org.apache.daffodil.runtime1.processors.unparsers.UState
+/**
+ * A TypeCalculator is a class that performs some kind of conversion from one DataValuePrimitive
+ * to another DataValuePrimitive. In general, this is done to convert a parsed physical
+ * representation from the data to a logical representation that goes in the infoset, and
+ * reverse on unparse. The former is done in the inputTypeCalc functions, and the latter in the
+ * outputTypeCalc functions. Generally the conversion is to a different type (e.g. xs:int to
+ * xs:string), but this need not be the case.
+ *
+ * The different TypeCalculator implementations allow for different conversions based on
+ * different properties provided in the schema (e.g. repType, enumerations, unions, repValues,
Review Comment:
You can have two different simple types with enumerations/repValues defined that are unioned by another simple type. Here's a test we have of this:
https://github.com/apache/daffodil/blob/main/daffodil-test/src/test/resources/org/apache/daffodil/extensions/type_calc/inputTypeCalc.tdml#L66-L80
I'm not sure if we actually use unions with repValues in any schemas, but I do see use a xs:unions.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -223,159 +186,34 @@ class KeysetValueTypeCalculatorUnordered(
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
valueMap.get(x) match {
- case Some(a) => (a, Maybe.Nope)
- case None =>
- (DataValue.NoValue, One(s"Value ${x} not found in enumeration dfdlx:repValues"))
+ case Some(a) => Right(a)
+ case None => Left(s"Value ${x} not found in enumeration dfdlx:repValues")
}
}
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
unparseMap.get(x) match {
- case Some(v) => (v, Maybe.Nope)
- case None => (DataValue.NoValue, One(s"Value ${x} not found in enumeration"))
+ case Some(v) => Right(v)
+ case None => Left(s"Value ${x} not found in enumeration")
}
}
}
-class ExpressionTypeCalculator(
- private val maybeInputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- private val maybeOutputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- srcType: NodeInfo.Kind,
- dstType: NodeInfo.Kind,
-) extends TypeCalculator(srcType, dstType) {
-
- /*
- * objects with Delay arguments for functional programming construction of
- * cyclic graphs, need a way to force the delays, resulting in an ordinary
- * (though cyclic) data structure.
- */
- final override def initialize(): Unit = {
- super.initialize()
- maybeInputTypeCalc
- maybeOutputTypeCalc
- }
-
- override def supportsParse = maybeInputTypeCalc.isDefined
- override def supportsUnparse = maybeOutputTypeCalc.isDefined
-
- /*
- * Compiling DPath expressions may need to evaluate typeCalculators in order to lookup their srcType and dstType.
- * To prevent circular dependencies, this means that the underlying expressions must be lazy.
- *
- * Since these fields must be lazy, we cannot use them to determine supportsParse or supportUnparse
- */
- lazy val maybeInputTypeCalc = maybeInputTypeCalcDelay.value
- lazy val maybeOutputTypeCalc = maybeOutputTypeCalcDelay.value
-
- // The class TypeValueCalc will verify that supports(Un)Parse is true when nessasary
- // Therefore, if we ever call the below functions, we know that the relevent Maybe object is defined.
-
- // TODO, pass x into DPath state
-
+class IdentityTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
Review Comment:
It was previously used when the repType and simpleType bases were the same, for example both are xs:string. I'm not actually sure if int to int works, but I can add a test for it.
I'm also not sure the use case for it, but I was thinking maybe it might be useful to use the same rep type for multiple logical types. E.g.
```xml
<simpleType name="rep" dfdl:properties="...">
<restriction base="xs:int" />
</simpleType>
<simplType name="intToString" dfdl:repType="rep">
<restriction base="xs:string">
<enumeration value="1" dfdl:repValues="1" />
...
</restriction>
</simpleType>
<simplType name="intToInt" dfdl:repType="rep">
<restriction base="xs:int">
<enumeration value="1" dfdl:repValues="1" />
...
</restriction>
</simpleType>
```
I'm not sure if this is actually useful, or even if it works, but I assumed there was a reason for the identity transform.
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] mbeckerle commented on a diff in pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "mbeckerle (via GitHub)" <gi...@apache.org>.
mbeckerle commented on code in PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#discussion_r1303614199
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -223,159 +186,34 @@ class KeysetValueTypeCalculatorUnordered(
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
valueMap.get(x) match {
- case Some(a) => (a, Maybe.Nope)
- case None =>
- (DataValue.NoValue, One(s"Value ${x} not found in enumeration dfdlx:repValues"))
+ case Some(a) => Right(a)
+ case None => Left(s"Value ${x} not found in enumeration dfdlx:repValues")
}
}
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = {
+ ): Either[Error, DataValuePrimitiveNullable] = {
unparseMap.get(x) match {
- case Some(v) => (v, Maybe.Nope)
- case None => (DataValue.NoValue, One(s"Value ${x} not found in enumeration"))
+ case Some(v) => Right(v)
+ case None => Left(s"Value ${x} not found in enumeration")
}
}
}
-class ExpressionTypeCalculator(
- private val maybeInputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- private val maybeOutputTypeCalcDelay: Delay[Maybe[CompiledExpression[AnyRef]]],
- srcType: NodeInfo.Kind,
- dstType: NodeInfo.Kind,
-) extends TypeCalculator(srcType, dstType) {
-
- /*
- * objects with Delay arguments for functional programming construction of
- * cyclic graphs, need a way to force the delays, resulting in an ordinary
- * (though cyclic) data structure.
- */
- final override def initialize(): Unit = {
- super.initialize()
- maybeInputTypeCalc
- maybeOutputTypeCalc
- }
-
- override def supportsParse = maybeInputTypeCalc.isDefined
- override def supportsUnparse = maybeOutputTypeCalc.isDefined
-
- /*
- * Compiling DPath expressions may need to evaluate typeCalculators in order to lookup their srcType and dstType.
- * To prevent circular dependencies, this means that the underlying expressions must be lazy.
- *
- * Since these fields must be lazy, we cannot use them to determine supportsParse or supportUnparse
- */
- lazy val maybeInputTypeCalc = maybeInputTypeCalcDelay.value
- lazy val maybeOutputTypeCalc = maybeOutputTypeCalcDelay.value
-
- // The class TypeValueCalc will verify that supports(Un)Parse is true when nessasary
- // Therefore, if we ever call the below functions, we know that the relevent Maybe object is defined.
-
- // TODO, pass x into DPath state
-
+class IdentityTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
override def inputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "inputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
override def outputTypeCalc(
x: DataValuePrimitive,
xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) =
- Assert.invariantFailed(
- "outputTypeCalc not implemented on ExpressionTypeCalculator. Call the more specialized forms directly",
- )
-
- override def inputTypeCalcParse(
- state: PState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- val ans = Maybe(maybeInputTypeCalc.get.evaluate(state))
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- if (ans.isDefined) {
- DataValue.unsafeFromAnyRef(ans.get)
- } else {
- DataValue.NoValue;
- }
- }
- override def outputTypeCalcUnparse(
- state: UState,
- context: RuntimeData,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): DataValuePrimitiveNullable = {
- val dstate = state.dState
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- val ans = maybeOutputTypeCalc.get.evaluate(state)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- DataValue.unsafeFromAnyRef(ans)
- }
-
- override def inputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = x
- dstate.logicalValue = DataValue.NoValue
-
- maybeInputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
-
- }
- override def outputTypeCalcRun(
- dstate: DState,
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): Unit = {
- val oldRepValue = dstate.repValue
- val oldLogicalValue = dstate.logicalValue
- dstate.repValue = DataValue.NoValue
- dstate.logicalValue = x
-
- maybeOutputTypeCalc.get.run(dstate)
-
- dstate.repValue = oldRepValue
- dstate.logicalValue = oldLogicalValue
- }
-}
-
-class IdentifyTypeCalculator(srcType: NodeInfo.Kind) extends TypeCalculator(srcType, srcType) {
- override def inputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
- override def outputTypeCalc(
- x: DataValuePrimitive,
- xType: NodeInfo.Kind,
- ): (DataValuePrimitiveNullable, Maybe[Error]) = (x, Maybe.Nope)
+ ): Either[Error, DataValuePrimitiveNullable] = Right(x)
}
class UnionTypeCalculator(
Review Comment:
I'd rather take these union things out. A repType should just be an integer, and typically isn't going to have facets, just DFDL properties. It's not visible at all in the infoset so there is no notion of an invalid repType value.
If a simple type that uses enumerations and repValue(s) is a union... that feels very problematic to me and I'd like to eliminate that possibility.
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [daffodil] mbeckerle commented on a diff in pull request #1070: Remove dfdlx:inputTypeCalc and dfdlx:outputTypeCalc
Posted by "mbeckerle (via GitHub)" <gi...@apache.org>.
mbeckerle commented on code in PR #1070:
URL: https://github.com/apache/daffodil/pull/1070#discussion_r1303604024
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala:
##########
@@ -21,135 +21,98 @@ import scala.collection.immutable.HashMap
import scala.collection.immutable.HashSet
import org.apache.daffodil.lib.exceptions.Assert
-import org.apache.daffodil.lib.util.Delay
import org.apache.daffodil.lib.util.Maybe
-import org.apache.daffodil.lib.util.Maybe.One
import org.apache.daffodil.lib.util.Numbers
-import org.apache.daffodil.lib.xml.QNameBase
-import org.apache.daffodil.runtime1.dpath.DState
import org.apache.daffodil.runtime1.dpath.NodeInfo
-import org.apache.daffodil.runtime1.dsom.CompiledExpression
import org.apache.daffodil.runtime1.infoset.DataValue
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitive
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitiveNullable
import org.apache.daffodil.runtime1.processors.parsers.PState
import org.apache.daffodil.runtime1.processors.parsers.ParseError
import org.apache.daffodil.runtime1.processors.unparsers.UState
+/**
+ * A TypeCalculator is a class that performs some kind of conversion from one DataValuePrimitive
+ * to another DataValuePrimitive. In general, this is done to convert a parsed physical
+ * representation from the data to a logical representation that goes in the infoset, and
+ * reverse on unparse. The former is done in the inputTypeCalc functions, and the latter in the
+ * outputTypeCalc functions. Generally the conversion is to a different type (e.g. xs:int to
+ * xs:string), but this need not be the case.
Review Comment:
I'd prefer to not support anything other than int->string. But we can make further changes later to restrict that.
I do not think string transformation by lookup tables (which is what string-string really kind of is) would ever become part of the DFDL standard because it's too far down the slippery slope of transformation.
--
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.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org