public final class MultipleAssignmentSupport
extends Object
Runtime helpers used by the GEP-20 multi-assignment destructuring bytecode.
These are called from generated bytecode only. User code should not rely on them.
| Type Params | Return Type | Name and description |
|---|---|---|
|
public static Object |
nonTailRestSlice(Object rhs, int fromIndex, int toIndex)Resolve the value for a head or middle rest binding. |
|
public static Object |
tailRest(Object rhs, int fromIndex, Iterator<?> seq)Resolve the value for a tail rest binding ( *t) at declarator index
fromIndex. |
Resolve the value for a head or middle rest binding. Requires a sized, indexable RHS
(List, CharSequence, or array — or any other receiver with a non-reversing
getAt(IntRange)); for other RHS types this routes through the MOP so that:
getAt(IntRange) extension) fail fast with
MissingMethodException — preventing silent materialisation of
unbounded sources.Stream RHS resolves StreamGroovyMethods.getAt(Stream, IntRange),
which rejects the destructuring slice's reverse range with
IllegalArgumentException("reverse range") — also fail-fast, also
no materialisation. (Head/middle rest from Stream is rejected at
compile time under @CompileStatic; the IAE only surfaces in
dynamic mode.)When the RHS is shorter than the sum of fixed slots around the rest, the computed range
is inverted. DGM's getAt(IntRange) would reverse an inverted range; for destructuring
we want an empty slice instead, so this helper short-circuits that case for the sized fast
paths (List/CharSequence/array). Other indexable receivers are responsible for their own
bounds handling.
rhs - the original RHS valuefromIndex - positive index where the slice beginstoIndex - negative index where the slice ends (inclusive) Resolve the value for a tail rest binding (*t) at declarator index
fromIndex. The GEP-20 dispatch model has three paths:
Stream<T>: wrap the already-advanced iterator
in a fresh sequential Stream and chain onClose to the
original. The new Stream reports no spliterator characteristics
(preserving them would require reading the original spliterator,
which is mutually exclusive with the iterator path used for head
extraction).getAt(IntRange).
Implemented as fast-path instanceof branches for
List, CharSequence, and Java arrays (size-aware so
out-of-bounds fromIndex returns the canonical empty value
without calling user code), with an MOP-dispatched fallback for
any other Path B receiver — BitSet (returns
BitSet), user custom classes, etc.The actual instanceof checks are ordered for performance
(List/CharSequence/array fast paths first, then Stream, then MOP
fallback, then iterator) but the conceptual dispatch order is A, then
B, then C.
Primitive streams (IntStream, LongStream,
DoubleStream) are not subtypes of Stream<T> and therefore
fall through to Path B (if they expose getAt(IntRange)) or
Path C; their elements are boxed by the underlying iterator.
rhs - the original RHS valuefromIndex - the declarator position of the rest bindingseq - the iterator that has already yielded the preceding fixed-slot values