stevedlawrence commented on code in PR #901:
URL: https://github.com/apache/daffodil/pull/901#discussion_r1067276335
##########
daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala:
##########
@@ -404,76 +542,117 @@ class CodeGeneratorState(private val root: ElementBase) {
finalStructs += struct
}
- def addSimpleTypeStatements(initERDStatement: String, initSelfStatement:
String, parseStatement: String, unparseStatement: String): Unit = {
- if (initERDStatement.nonEmpty) structs.top.initERDStatements +=
initERDStatement
- if (initSelfStatement.nonEmpty) structs.top.initSelfStatements +=
initSelfStatement
+ // Add C code to initialize, parse, and unparse a primitive value element
+ def addSimpleTypeStatements(initERDStatement: String, parseStatement:
String, unparseStatement: String): Unit = {
+ if (initERDStatement.nonEmpty) {
+ if (hasChoice)
+ structs.top.initChoiceStatements += initERDStatement
+ else
+ structs.top.initERDStatements += initERDStatement
+ }
if (parseStatement.nonEmpty) structs.top.parserStatements += parseStatement
if (unparseStatement.nonEmpty) structs.top.unparserStatements +=
unparseStatement
}
- def addComplexTypeStatements(child: ElementBase): Unit = {
+ // Generate C code to initialize, parse, and unparse a child element
+ def addPerChildStatements(child: ElementBase): Unit = {
val C = cStructName(child)
- val e = child.name
- val hasChoice = structs.top.initChoiceStatements.nonEmpty
- val arraySize = if (child.occursCountKind == OccursCountKind.Fixed)
child.maxOccurs else 0
+ val e = child.namedQName.local
+ // Generate a choice statement case if the child is in a choice element
+ val hasChoice = structs.top.initChoiceStatements.nonEmpty
if (hasChoice) {
+ val position = child.position
structs.top.initChoiceStatements ++=
ChoiceBranchKeyCooker.convertConstant(
child.choiceBranchKey, child, forUnparse = false).map { key => s"
case $key:"}
-
- val offset = child.position - 1
- val initChoiceStatement = s" instance->_choice = $offset;"
- val parseStatement = s" case $offset:"
- val unparseStatement = s" case $offset:"
-
- structs.top.initChoiceStatements += initChoiceStatement
- structs.top.parserStatements += parseStatement
- structs.top.unparserStatements += unparseStatement
+ structs.top.initChoiceStatements += s" instance->_choice =
$position;"
+ structs.top.parserStatements += s" case $position:"
+ structs.top.unparserStatements += s" case $position:"
}
+ val indent1 = if (hasChoice) " " else ""
- def addStatements(deref: String): Unit = {
- val initChoiceStatement = s" ${C}_initERD(&instance->$e$deref);"
- val initERDStatement = s" ${C}_initERD(&instance->$e$deref);"
- val initSelfStatement = s" ${C}_initSelf(&instance->$e$deref);"
- val moreIndent = if (hasChoice) " " else ""
- val parseStatement =
- s"""$moreIndent ${C}_parseSelf(&instance->$e$deref, pstate);
- |$moreIndent if (pstate->error) return;""".stripMargin
- val unparseStatement =
- s"""$moreIndent ${C}_unparseSelf(&instance->$e$deref, ustate);
- |$moreIndent if (ustate->error) return;""".stripMargin
+ // Add an array if the child occurs multiple times
+ val hasArray = arrayMaxOccurs(child) > 0
+ val deref = if (hasArray) "[i]" else ""
+ val indent2 = if (hasArray) " " else ""
+ if (hasArray) pushArray(child)
+ // Generate statements to initialize, parse, and unparse the child
+ Runtime2CodeGenerator.generateCode(child.enclosedElement, this)
+ if (!child.isSimpleType) {
if (hasChoice)
- structs.top.initChoiceStatements += initChoiceStatement
+ structs.top.initChoiceStatements += s"$indent2
${C}_initERD(&instance->$e$deref, (InfosetBase *)instance);"
else
- structs.top.initERDStatements += initERDStatement
- structs.top.initSelfStatements += initSelfStatement
- structs.top.parserStatements += parseStatement
- structs.top.unparserStatements += unparseStatement
+ structs.top.initERDStatements += s"$indent2
${C}_initERD(&instance->$e$deref, (InfosetBase *)instance);"
+ structs.top.parserStatements +=
+ s"""$indent1$indent2 ${C}_parseSelf(&instance->$e$deref, pstate);
+ |$indent1$indent2 if (pstate->error) return;""".stripMargin
+ structs.top.unparserStatements +=
+ s"""$indent1$indent2 ${C}_unparseSelf(&instance->$e$deref, ustate);
+ |$indent1$indent2 if (ustate->error) return;""".stripMargin
}
- if (arraySize > 0)
- for (i <- 0 until arraySize)
- addStatements(s"[$i]")
- else
- addStatements("")
- if (hasChoice) {
- val initChoiceStatement = s" break;"
- val parseStatement = s" break;"
- val unparseStatement = s" break;"
+ // Generate statements to align the next element
+ val mustAlign = child.endingAlignmentApprox.nBits >
child.priorAlignmentApprox.nBits
Review Comment:
> there still was a need for extra alignment between two elements aligned to
8 bits
because the schema writer had used an empty sequence aligned to 32
bits following a hexBinary element to artificially pad the hexBinary
element's length to a multiple of 32 bits, and furthermore, the schema
compiler had optimized away that empty sequence so the only place that
extra 32-bit alignment could be found was in the hexBinary element's
endingAlignmentApprox.nBits (32) which was bigger than its
priorAlignmentApprox.nBits (8) and its alignmentValueInBits (8).
I'm not sure why DFDL would have optimized out the sequence if there's
required alignment. That sounds like it might be a bug in the compiler if
that's the case.
It feels like runtime2 should be inserting framing code for sequences that
are not known to be aligned, in addition to elements. Would it work to add the
same `isKnownToBeAligned` and `parse_align` logic in
`orderedSequeneGenrateConfig` or wherever runtime2 walks into sequences?
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]