The issues identified in Analysis: Schema Compiler Backpointers/Copying require some design and test planning.
IsHidden
This flag will be stored on infoset elements at the time they are created. This requires using a stack at runtime that keeps track of what Terms, specifically what sequence group references are in the dynamic context, and if so, whether that sequence group reference is a hidden-group reference.
The Unparser, specifically InfosetInputter contains a "TRD stack" which is a stack of the TermRuntimeData objects for every Term in dynamic context.
Design alternatives
- TRD Stack
- Move the TRD Stack from the InfosetInputter so it is a member of the ParseOrUnparseState base class, where it is visible for both parsing and unparsing
- Update parsers to also maintain this stack.
- Whenever an infoset element is created, scan the stack to see if any Sequence Group Ref that is a hidden group ref, is on stack. If so mark the infoset element as hidden.
- Maintain State member
- Add an isHiddenContext var member to ParseOrUnparseState
- In the parse1 => parse and unparse1 => unparse calls, examine the TRD of the current parser.
- If the TRD of the current processor is a hidden group ref, and the isHiddenContext is false, then invoke the parse/unparse method within a code branch that will set the isHiddenContext to true, and set it back to false upon unwinding.
- A try-finally type of unwind-protect could be used, but should not be necessary, as parsers are supposed to unwind the stack without throws, and all throws are fatal when unparsing.
- Otherwise, invoke the parse/unparse method normally, which does not affect the state of isHiddenContext.
Tradeoffs:
- The TRD Stack incurs push/pop overhead only for Term processors, not for the primitive processors of delimiters, alignment regions, etc.
- The state member incurs a small overhead for every processor to determine if it is a hidden-group ref.
- The state member is more centralized solution in the code base, requiring only the member in the state, and code in the Parser and Unparser bases/traits in the parse1/unparse1 methods.
- The TRD Stack may be necessary for other things - it is needed for Unparsing at least in order for InfosetInputters to be able to properly construct element events.
Resolved: Prefer maintaining a state member isHiddenContext and then setting a member of infoset elements when constructed.