...
Within the DPath processing code, Daffodil will define 2 case classes, a UDFunctionCallExpr and a UDFunctionCall. The dResultType and dArgTypes arguments for UDFArgsListExpr will be inferred from the udFunctionClass the functionClass as shown above. The Expression functionObject will be set to the below.
Code Block |
---|
|
UDFunctionCallExpr(functionQNameString, functionQName, args, dResultType, dArgTypes, UDFunctionCall(_, functionClassObject, udFunctionClass)) |
...
UDFunctionCallExpr will extend Daffodil's FunctionCallBase, and implement inherentType, targetTypeForSubexpression and compiledDPath. compiledDPath will call UDFunctionCall. UDFunctionCall will call fEvaluate using its invoke method.
Code Block |
---|
|
case class UDFunctionCallExpr(nameAsParsed: String, fnQName: RefQName, args: List[Expression],
resultType: NodeInfo.Kind, argsTypes: List[NodeInfo.Kind], constructor: List[CompiledDPath] => RecipeOp)
extends FunctionCallBase(nameAsParsed, fnQName, args) {
lazy val argsToArgType = (args zip argsTypes).toMap
override lazy val inherentType = resultType
override def targetTypeForSubexpression(childExpr: Expression): NodeInfo.Kind = {
argsToArgType.get(childExpr) match {
case Some(argType) => argType
case None => {
Assert.invariantFailed("subexpression %s is not an argument.".format(subexp))
}
}
}
override lazy val compiledDPath = {
val recipes = args.map { _.compiledDPath }
val res = new CompiledDPath(constructor(recipes) +: conversions)
res
}
}
case class UDFunctionCall(recipes: List[CompiledDPath], functionClassObject: Object, udfEvaluate: Method)
extends FNArgsList(recipes) {
override def computeValues(values: List[Any], dstate: DState) = {
val res = udfEvaluate.invoke(functionClassObject, values: _*) //might need to explicitly cast values to type Object before hand
res
}
} |