-
Notifications
You must be signed in to change notification settings - Fork 110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Includes various small fixes for tagless parameters, expression groups, and system macro invocations. #975
Conversation
…s, and system macro invocations.
@@ -3361,6 +3361,10 @@ private void setCheckpointAfterValueHeader() { | |||
case START_CONTAINER: | |||
setCheckpoint(CheckpointLocation.AFTER_CONTAINER_HEADER); | |||
break; | |||
case NEEDS_INSTRUCTION: | |||
// A macro invocation header has just been read. | |||
setCheckpoint(CheckpointLocation.BEFORE_UNANNOTATED_TYPE_ID); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This moves the cursor past the macro invocation header, positioning it on the first argument (if any). This method is called when parsing expression groups.
@@ -1449,7 +1449,7 @@ private void readGroupExpression(Macro.Parameter parameter, List<Expression.EExp | |||
int startIndex = expressions.size(); | |||
expressions.add(Expression.Placeholder.INSTANCE); | |||
boolean isSingleton = true; | |||
while (nextGroupedValue() != Event.NEEDS_INSTRUCTION) { | |||
while (nextGroupedValue() != Event.NEEDS_INSTRUCTION || isMacroInvocation()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NEEDS_INSTRUCTION is used either when the end of the group has been reached, or when a macro invocation header has been encountered. When it's the latter, we need to read the invocation as an expression to continue progressing through the group.
@@ -1560,7 +1560,7 @@ protected PresenceBitmap loadPresenceBitmapIfNecessary(List<Macro.Parameter> sig | |||
|
|||
@Override | |||
protected boolean isMacroInvocation() { | |||
return valueTid.isMacroInvocation; | |||
return valueTid != null && valueTid.isMacroInvocation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is now called when the cursor may be at the end of the group, at which point valueTid
will be null
.
List<SymbolToken> annotations = getAnnotations(); | ||
boolean isSystemMacro = !annotations.isEmpty() && SystemSymbols_1_1.ION.getText().equals(annotations.get(0).getText()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The added macroInvocationInTaggedExpressionGroup
test exercises this because it invokes the values
macro from a context that does not export the Ion 1.1 system macros. The invocation looks like (:$ion::values ...)
@@ -859,12 +859,12 @@ class IonRawBinaryWriter_1_1 internal constructor( | |||
thisContainerTotalLength++ | |||
} else if (isTagless) { | |||
// End tagless group -- write the number of expressions, end with FlexUInt 0 | |||
thisContainerTotalLength += writeCurrentContainerLength(lengthPrefixPreallocation) | |||
thisContainerTotalLength += writeCurrentContainerLength(maxOf(1, lengthPrefixPreallocation)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now symmetrical with stepInExpressionGroup
for this case, which always reserves at least one byte for the length. Without this fix, the byte is reserved in the buffer and a patch point is added, resulting in an erroneous extra byte in the final output. The same can be said for the other change in this file.
This change is verified by the added taglessExpressionGroup
test.
buffer.writeByte(FlexInt.ZERO) | ||
thisContainerTotalLength++ | ||
} else if (currentContainer.isLengthPrefixed) { | ||
// Length-prefixed, tagged -- write the number of bytes | ||
thisContainerTotalLength += writeCurrentContainerLength(lengthPrefixPreallocation) | ||
thisContainerTotalLength += writeCurrentContainerLength(maxOf(1, lengthPrefixPreallocation)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exercised by the added macroInvocationInTaggedExpressionGroup
test.
val parameterEncoding = when (annotations.size) { | ||
0 -> Macro.ParameterEncoding.Tagged | ||
1 -> { | ||
val encodingText = annotations[0].text | ||
val encoding = Macro.ParameterEncoding.entries.singleOrNull { it.ionTextName == encodingText } | ||
if (encoding == null) { | ||
// TODO: Check for macro-shaped parameter encodings, and only if it's still null, we throw. | ||
throw IonException("unsupported parameter encoding $annotations") | ||
} | ||
encoding | ||
} | ||
2 -> TODO("Qualified references for macro-shaped parameters") | ||
else -> throw IonException("unsupported parameter encoding $annotations") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This patch is contributed by @popematt, and is exercised by the added taglessExpressionGroup
test.
@@ -136,6 +141,30 @@ private static void writeMacroSignature(IonRawWriter_1_1 writer, Map<String, Int | |||
writer.stepOut(); | |||
} | |||
|
|||
private static void writeMacroSignatureFromDatagram(IonRawWriter_1_1 writer, Map<String, Integer> symbols, IonDatagram... signature) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows us to specify tagless encodings. The other variant just takes a String
, without a way to add an encoding annotation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fascinating use of IonDatagram for "unmodeled sequence of values". I did a double-take.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
@@ -136,6 +141,30 @@ private static void writeMacroSignature(IonRawWriter_1_1 writer, Map<String, Int | |||
writer.stepOut(); | |||
} | |||
|
|||
private static void writeMacroSignatureFromDatagram(IonRawWriter_1_1 writer, Map<String, Integer> symbols, IonDatagram... signature) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fascinating use of IonDatagram for "unmodeled sequence of values". I did a double-take.
if (parameter.size() > 2) { | ||
throw new IllegalStateException("Parameters can only have two components: a name and a cardinality."); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (parameter.size() > 2) { | |
throw new IllegalStateException("Parameters can only have two components: a name and a cardinality."); | |
} | |
if (parameter.size() > 2) { | |
throw new IllegalStateException("Parameters can only have two components: a name and a cardinality."); | |
} | |
if (parameter.size() < 1) { | |
throw new IllegalStateException("Parameters must have at least one component: a name."); | |
} |
writer.stepInEExp(0, false, expectedMacro); { | ||
writer.stepInExpressionGroup(true); { | ||
writer.stepInEExp(SystemMacro.Values); { | ||
writer.writeString("bar"); | ||
} writer.stepOut(); | ||
} writer.stepOut(); | ||
} writer.stepOut(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you're also using the stepIn/Out idiom from old IonJava tests :D
Description of changes:
Includes various small fixes for tagless parameters, expression groups, and system macro invocations. See comments inline for a guide.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.