Skip to content

Commit

Permalink
Adds support for early step out of macro invocations that expand to s…
Browse files Browse the repository at this point in the history
…treams.
  • Loading branch information
tgregg committed Jan 8, 2025
1 parent 5c13821 commit 9d175b3
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2045,11 +2045,18 @@ public Event stepIntoContainer() {
@Override
public Event stepOutOfContainer() {
if (isEvaluatingEExpression) {
// TODO step out of the macro evaluator only if it's in a container. Otherwise, finish the evaluation early
// and step out of the parent.
macroEvaluatorIonReader.stepOut();
event = Event.NEEDS_INSTRUCTION;
return event;
if (macroEvaluatorIonReader.getDepth() > 0) {
// The user has stepped into a container produced by the evaluator. Therefore, this stepOut() call
// must step out of that evaluated container.
macroEvaluatorIonReader.stepOut();
event = Event.NEEDS_INSTRUCTION;
return event;
} else {
// The evaluator is not producing a container value. Therefore, the user intends for this stepOut() call
// to step out of the parent container of the e-expression being evaluated. This terminates e-expression
// evaluation.
isEvaluatingEExpression = false;
}
}
return super.stepOutOfContainer();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6309,8 +6309,35 @@ public void earlyStepOutDelimitedStructThatContainsMacroInvocationWithTaggedExpr
closeAndCount();
}

// TODO add a test that modifies the above to step out after beginning macro evaluation but before exhausting it.
// This should end evaluation early and step out of the struct.
@ParameterizedTest(name = "constructFromBytes={0}")
@ValueSource(booleans = {true, false})
public void partialEvaluationOfMacroInvocationInDelimitedContainer(boolean constructFromBytes) throws Exception {
reader = readerForIon11(bytes(
0xF3, // Delimited struct start
0xFF, 'a', // FlexSym field name 'a'
0x06, 0x02, // Macro invocation 6 (delta), AEB 2 (group)
0x0D, // 6-byte expression group
0x61, 0x01, // 1
0x61, 0x02, // 2
0x61, 0x03, // 3
0x01, 0xF0, // Delimited struct end
0x93, 'a', 'b', 'c'
),
constructFromBytes
);
assertSequence(
next(IonType.STRUCT),
STEP_IN,
next(IonType.INT),
bigIntegerValue(BigInteger.ONE),
// Step out before exhausting all values produced by the 'delta' invocation.
STEP_OUT,
next(IonType.STRING),
stringValue("abc"),
next(null)
);
closeAndCount();
}

@ParameterizedTest(name = "constructFromBytes={0}")
@ValueSource(booleans = {true, false})
Expand Down Expand Up @@ -6452,6 +6479,69 @@ public void fillMultipleNestedDelimitedLists() throws Exception {
closeAndCount();
}

@ParameterizedTest(name = "constructFromBytes={0}")
@ValueSource(booleans = {true, false})
public void partialEvaluationOfMacroInvocationInPrefixedContainer(boolean constructFromBytes) throws Exception {
reader = readerForIon11(bytes(
0xB9, // List length 9
0x06, 0x02, // Macro invocation 6 (delta), AEB 2 (group)
0x0D, // 6-byte expression group
0x61, 0x01, // 1
0x61, 0x02, // 2
0x61, 0x03, // 3
0x01, 0x02, // Macro invocation 1 (values), AEB 2 (group)
0x09, // 4-byte expression group
0x93, 'a', 'b', 'c'
),
constructFromBytes
);
assertSequence(
next(IonType.LIST),
STEP_IN,
next(IonType.INT),
bigIntegerValue(BigInteger.ONE),
// Step out before exhausting all values produced by the 'delta' invocation.
STEP_OUT,
next(IonType.STRING),
stringValue("abc"),
next(null)
);
closeAndCount();
}

@ParameterizedTest(name = "constructFromBytes={0}")
@ValueSource(booleans = {true, false})
public void earlyStepOutOfContainerInMacroInvocation(boolean constructFromBytes) throws Exception {
reader = readerForIon11(bytes(
0x01, 0x02, // Macro invocation 1 (values), AEB 2 (group)
0x0F, // 7-byte expression group
0xB4, // 4-byte list
0x61, 0x01, // 1
0x61, 0x02, // 2
0x61, 0x03, // 3
0x01, 0x02, // Macro invocation 1 (values), AEB 2 (group)
0x09, // 4-byte expression group
0x93, 'a', 'b', 'c'
),
constructFromBytes
);
assertSequence(
next(IonType.LIST),
STEP_IN,
next(IonType.INT),
bigIntegerValue(BigInteger.ONE),
// Step out before exhausting all values in the list.
STEP_OUT,
next(IonType.INT),
bigIntegerValue(BigInteger.valueOf(3)),
// This ends the 'values' invocation.
next(IonType.STRING),
stringValue("abc"),
next(null)
);
closeAndCount();
}

// TODO test continuable reading and skipping of non-prefixed macro invocations.
// TODO test skipping macro invocations (especially length-prefixed ones) that expand to system values.
// TODO Ion 1.1 symbol tables with all kinds of annotation encodings (opcodes E4 - E9, inline and SID)
Expand Down

0 comments on commit 9d175b3

Please sign in to comment.