@CompilerDirectives.SlowPath
public Object matchOperator(String string) {
// TODO(CS) merge with match
final Frame frame = Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_WRITE, false);
final RubyContext context = getContext();
final byte[] stringBytes = string.getBytes(StandardCharsets.UTF_8);
final Matcher matcher = regex.matcher(stringBytes);
final int match = matcher.search(0, stringBytes.length, Option.DEFAULT);
if (match != -1) {
final Region region = matcher.getEagerRegion();
final Object[] values = new Object[region.numRegs];
for (int n = 0; n < region.numRegs; n++) {
final int start = region.beg[n];
final int end = region.end[n];
final Object groupString;
if (start > -1 && end > -1) {
groupString = context.makeString(string.substring(start, end));
} else {
groupString = getContext().getCoreLibrary().getNilObject();
}
values[n] = groupString;
final FrameSlot slot = frame.getFrameDescriptor().findFrameSlot("$" + n);
if (slot != null) {
frame.setObject(slot, groupString);
}
}
if (values.length > 0) {
final FrameSlot slot = frame.getFrameDescriptor().findFrameSlot("$+");
int nonNil = values.length - 1;
while (values[nonNil] == getContext().getCoreLibrary().getNilObject()) {
nonNil--;
}
if (slot != null) {
frame.setObject(slot, values[nonNil]);
}
}
final RubyMatchData matchObject = new RubyMatchData(context.getCoreLibrary().getMatchDataClass(), values);
final FrameSlot slot = frame.getFrameDescriptor().findFrameSlot("$~");
if (slot != null) {
frame.setObject(slot, matchObject);
}
return matcher.getBegin();
} else {
final FrameSlot slot = frame.getFrameDescriptor().findFrameSlot("$~");
if (slot != null) {
frame.setObject(slot, getContext().getCoreLibrary().getNilObject());
}
return getContext().getCoreLibrary().getNilObject();
}
}