All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.truffle.js.runtime.util.TRegexUtil Maven / Gradle / Ivy

/*
 * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * The Universal Permissive License (UPL), Version 1.0
 *
 * Subject to the condition set forth below, permission is hereby granted to any
 * person obtaining a copy of this software, associated documentation and/or
 * data (collectively the "Software"), free of charge and under any and all
 * copyright rights in the Software, and any and all patent rights owned or
 * freely licensable by each licensor hereunder covering either (i) the
 * unmodified Software as contributed to or provided by such licensor, or (ii)
 * the Larger Works (as defined below), to deal in both
 *
 * (a) the Software, and
 *
 * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
 * one is included with the Software each a "Larger Work" to which the Software
 * is contributed by such licensors),
 *
 * without restriction, including without limitation the rights to copy, create
 * derivative works of, display, perform, and distribute the Software and make,
 * use, sell, offer for sale, import, export, have made, and have sold the
 * Software and the Larger Work(s), and to sublicense the foregoing rights on
 * either these or other terms.
 *
 * This license is subject to the following condition:
 *
 * The above copyright notice and either this complete permission notice or at a
 * minimum a reference to the UPL must be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.oracle.truffle.js.runtime.util;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Cached.Shared;
import com.oracle.truffle.api.dsl.GenerateCached;
import com.oracle.truffle.api.dsl.GenerateInline;
import com.oracle.truffle.api.dsl.GenerateUncached;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NeverDefault;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.ArityException;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
import com.oracle.truffle.api.interop.UnknownIdentifierException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.api.strings.TruffleString.SubstringByteIndexNode;
import com.oracle.truffle.js.lang.JavaScriptLanguage;
import com.oracle.truffle.js.nodes.JSGuards;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.Strings;
import com.oracle.truffle.js.runtime.objects.Undefined;
import com.oracle.truffle.js.runtime.util.TRegexUtil.Props.CompiledRegex;
import com.oracle.truffle.js.runtime.util.TRegexUtilFactory.InteropReadBooleanMemberNodeGen;
import com.oracle.truffle.js.runtime.util.TRegexUtilFactory.InteropReadIntArrayMemberNodeGen;
import com.oracle.truffle.js.runtime.util.TRegexUtilFactory.InteropReadIntMemberNodeGen;
import com.oracle.truffle.js.runtime.util.TRegexUtilFactory.InteropReadMemberNodeGen;
import com.oracle.truffle.js.runtime.util.TRegexUtilFactory.InteropReadStringMemberNodeGen;
import com.oracle.truffle.js.runtime.util.TRegexUtilFactory.InvokeExecMethodNodeGen;
import com.oracle.truffle.js.runtime.util.TRegexUtilFactory.InvokeGetGroupBoundariesMethodNodeGen;

public final class TRegexUtil {

    private TRegexUtil() {
        // should not be constructed
    }

    public static final class Props {
        private Props() {
            // should not be constructed
        }

        public static final class CompiledRegex {
            private CompiledRegex() {
                // should not be constructed
            }

            public static final String PATTERN = "pattern";
            public static final String FLAGS = "flags";
            public static final String EXEC = "exec";
            public static final String GROUP_COUNT = "groupCount";
            public static final String GROUPS = "groups";
        }

        public static final class Flags {
            private Flags() {
                // should not be constructed
            }

            public static final String SOURCE = "source";
            public static final String GLOBAL = "global";
            public static final String MULTILINE = "multiline";
            public static final String IGNORE_CASE = "ignoreCase";
            public static final String STICKY = "sticky";
            public static final String UNICODE = "unicode";
            public static final String DOT_ALL = "dotAll";
            public static final String HAS_INDICES = "hasIndices";
            public static final String UNICODE_SETS = "unicodeSets";
        }

        public static final class RegexResult {
            private RegexResult() {
                // should not be constructed
            }

            public static final String IS_MATCH = "isMatch";
            public static final String GET_START = "getStart";
            public static final String GET_END = "getEnd";
        }
    }

    private static final String NUMBER_OF_REGEX_RESULT_TYPES = "9";

    public static final class Constants {
        private Constants() {
            // should not be constructed
        }

        public static final int CAPTURE_GROUP_NO_MATCH = -1;
    }

    @GenerateInline
    @GenerateUncached
    public abstract static class InteropReadMemberNode extends Node {

        public abstract Object execute(Node node, Object obj, String key);

        @Specialization(guards = "objs.isMemberReadable(obj, key)", limit = NUMBER_OF_REGEX_RESULT_TYPES)
        static Object read(Object obj, String key, @CachedLibrary("obj") InteropLibrary objs) {
            try {
                return objs.readMember(obj, key);
            } catch (UnsupportedMessageException | UnknownIdentifierException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }

        @NeverDefault
        public static InteropReadMemberNode create() {
            return InteropReadMemberNodeGen.create();
        }

        public static InteropReadMemberNode getUncached() {
            return InteropReadMemberNodeGen.getUncached();
        }
    }

    @GenerateInline
    @GenerateUncached
    public abstract static class InteropReadIntMemberNode extends Node {

        public abstract int execute(Node node, Object obj, String key);

        @Specialization(guards = "objs.isMemberReadable(obj, key)", limit = NUMBER_OF_REGEX_RESULT_TYPES)
        static int read(Node node, Object obj, String key, @Cached InteropToIntNode coerceNode, @CachedLibrary("obj") InteropLibrary objs) {
            try {
                return coerceNode.execute(node, objs.readMember(obj, key));
            } catch (UnsupportedMessageException | UnknownIdentifierException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }

        @NeverDefault
        public static InteropReadIntMemberNode create() {
            return InteropReadIntMemberNodeGen.create();
        }

        public static InteropReadIntMemberNode getUncached() {
            return InteropReadIntMemberNodeGen.getUncached();
        }
    }

    @GenerateInline
    @GenerateUncached
    public abstract static class InteropReadIntArrayMemberNode extends Node {

        public abstract int[] execute(Node node, Object obj, String key);

        @Specialization(guards = "objs.isMemberReadable(obj, key)", limit = NUMBER_OF_REGEX_RESULT_TYPES)
        static int[] read(Node node, Object obj, String key, @Cached InteropToIntNode coerceNode, @CachedLibrary("obj") InteropLibrary objs, @CachedLibrary(limit = "1") InteropLibrary arrays) {
            try {
                Object interopArray = objs.readMember(obj, key);
                int length = (int) arrays.getArraySize(interopArray);
                int[] array = new int[length];
                for (int i = 0; i < length; i++) {
                    array[i] = coerceNode.execute(node, arrays.readArrayElement(interopArray, i));
                }
                return array;
            } catch (UnsupportedMessageException | UnknownIdentifierException | InvalidArrayIndexException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }

        @NeverDefault
        public static InteropReadIntArrayMemberNode create() {
            return InteropReadIntArrayMemberNodeGen.create();
        }

        public static InteropReadIntArrayMemberNode getUncached() {
            return InteropReadIntArrayMemberNodeGen.getUncached();
        }
    }

    @GenerateInline
    @GenerateUncached
    public abstract static class InteropReadBooleanMemberNode extends Node {

        public abstract boolean execute(Node node, Object obj, String key);

        @Specialization(guards = "objs.isMemberReadable(obj, key)", limit = NUMBER_OF_REGEX_RESULT_TYPES)
        static boolean read(Node node, Object obj, String key,
                        @Cached InteropToBooleanNode coerceNode,
                        @CachedLibrary("obj") InteropLibrary objs) {
            try {
                return coerceNode.execute(node, objs.readMember(obj, key));
            } catch (UnsupportedMessageException | UnknownIdentifierException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }

        @NeverDefault
        public static InteropReadBooleanMemberNode create() {
            return InteropReadBooleanMemberNodeGen.create();
        }

        public static InteropReadBooleanMemberNode getUncached() {
            return InteropReadBooleanMemberNodeGen.getUncached();
        }
    }

    @GenerateInline
    @GenerateUncached
    public abstract static class InteropReadStringMemberNode extends Node {

        public abstract TruffleString execute(Node node, Object obj, String key);

        @Specialization(guards = "objs.isMemberReadable(obj, key)", limit = "3")
        static TruffleString read(Node node, Object obj, String key,
                        @Cached InteropToStringNode coerceNode,
                        @CachedLibrary("obj") InteropLibrary objs) {
            try {
                return coerceNode.execute(node, objs.readMember(obj, key));
            } catch (UnsupportedMessageException | UnknownIdentifierException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }

        @NeverDefault
        public static InteropReadStringMemberNode create() {
            return InteropReadStringMemberNodeGen.create();
        }

        public static InteropReadStringMemberNode getUncached() {
            return InteropReadStringMemberNodeGen.getUncached();
        }
    }

    @GenerateInline
    @GenerateUncached
    public abstract static class InteropToBooleanNode extends Node {

        public abstract boolean execute(Node node, Object obj);

        @Specialization
        static boolean coerceDirect(boolean obj) {
            return obj;
        }

        @Specialization(guards = "objs.isBoolean(obj)", limit = "3")
        static boolean coerce(Object obj,
                        @CachedLibrary("obj") InteropLibrary objs) {
            try {
                return objs.asBoolean(obj);
            } catch (UnsupportedMessageException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }
    }

    @GenerateInline
    @GenerateUncached
    public abstract static class InteropToIntNode extends Node {

        public abstract int execute(Node node, Object obj);

        @Specialization
        static int coerceDirect(int obj) {
            return obj;
        }

        @Specialization(guards = "objs.fitsInInt(obj)", limit = "3")
        static int coerce(Object obj,
                        @CachedLibrary("obj") InteropLibrary objs) {
            try {
                return objs.asInt(obj);
            } catch (UnsupportedMessageException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }
    }

    @SuppressWarnings("truffle-inlining")
    @GenerateInline
    @GenerateUncached
    @ImportStatic(JSGuards.class)
    public abstract static class InteropToStringNode extends Node {

        public abstract TruffleString execute(Node node, Object obj);

        @Specialization
        static TruffleString coerceJavaString(String obj,
                        @Cached(inline = false) TruffleString.FromJavaStringNode fromJavaStringNode) {
            return Strings.fromJavaString(fromJavaStringNode, obj);
        }

        @Specialization
        static TruffleString coerceDirect(TruffleString obj,
                        @Cached @Shared TruffleString.SwitchEncodingNode switchEncoding) {
            return switchEncoding.execute(obj, TruffleString.Encoding.UTF_16);
        }

        @Specialization(guards = {"!isTruffleString(obj)", "objs.isString(obj)"}, limit = "3")
        static TruffleString coerce(Object obj,
                        @CachedLibrary("obj") InteropLibrary objs,
                        @Cached @Shared TruffleString.SwitchEncodingNode switchEncoding) {
            return Strings.interopAsTruffleString(obj, objs, switchEncoding);
        }
    }

    @GenerateInline
    @GenerateUncached
    @ImportStatic(CompiledRegex.class)
    public abstract static class InvokeExecMethodNode extends Node {

        public abstract Object execute(Node node, Object compiledRegex, Object input, long fromIndex);

        @Specialization(guards = "objs.isMemberInvocable(compiledRegex, EXEC)", limit = "3")
        static Object exec(Object compiledRegex, Object input, long fromIndex,
                        @CachedLibrary("compiledRegex") InteropLibrary objs) {
            try {
                return objs.invokeMember(compiledRegex, CompiledRegex.EXEC, input, fromIndex);
            } catch (UnsupportedMessageException | UnsupportedTypeException | ArityException | UnknownIdentifierException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }

        @NeverDefault
        public static InvokeExecMethodNode create() {
            return InvokeExecMethodNodeGen.create();
        }

        public static InvokeExecMethodNode getUncached() {
            return InvokeExecMethodNodeGen.getUncached();
        }
    }

    @GenerateInline
    @GenerateUncached
    public abstract static class InvokeGetGroupBoundariesMethodNode extends Node {

        public abstract int execute(Node node, Object regexResult, Object method, int groupNumber);

        @Specialization(guards = "objs.isMemberInvocable(regexResult, method)", limit = NUMBER_OF_REGEX_RESULT_TYPES)
        static int exec(Node node, Object regexResult, String method, int groupNumber,
                        @CachedLibrary("regexResult") InteropLibrary objs,
                        @Cached InteropToIntNode toIntNode) {
            try {
                return toIntNode.execute(node, objs.invokeMember(regexResult, method, groupNumber));
            } catch (UnsupportedMessageException | UnsupportedTypeException | ArityException | UnknownIdentifierException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }

        @NeverDefault
        public static InvokeGetGroupBoundariesMethodNode create() {
            return InvokeGetGroupBoundariesMethodNodeGen.create();
        }

        public static InvokeGetGroupBoundariesMethodNode getUncached() {
            return InvokeGetGroupBoundariesMethodNodeGen.getUncached();
        }
    }

    public static final class TRegexCompiledRegexAccessor {

        private TRegexCompiledRegexAccessor() {
        }

        public static Object pattern(Object compiledRegexObject, Node node, InteropReadStringMemberNode readPattern) {
            return readPattern.execute(node, compiledRegexObject, Props.CompiledRegex.PATTERN);
        }

        public static Object flags(Object compiledRegexObject, Node node, InteropReadMemberNode readFlags) {
            return readFlags.execute(node, compiledRegexObject, Props.CompiledRegex.FLAGS);
        }

        public static Object exec(Object compiledRegexObject, Object input, long fromIndex, Node node, InvokeExecMethodNode invokeExec) {
            return invokeExec.execute(node, compiledRegexObject, input, fromIndex);
        }

        public static int groupCount(Object regexResultObject, Node node, InteropReadIntMemberNode readGroupCount) {
            return readGroupCount.execute(node, regexResultObject, Props.CompiledRegex.GROUP_COUNT);
        }

        public static Object namedCaptureGroups(Object compiledRegexObject, Node node, InteropReadMemberNode readGroups) {
            return readGroups.execute(node, compiledRegexObject, Props.CompiledRegex.GROUPS);
        }
    }

    public static final class TRegexNamedCaptureGroupsAccessor {

        private TRegexNamedCaptureGroupsAccessor() {
        }

        public static boolean isNull(Object namedCaptureGroupsMap, InteropLibrary interop) {
            return interop.isNull(namedCaptureGroupsMap);
        }

        public static boolean hasGroup(Object namedCaptureGroupsMap, TruffleString name, InteropLibrary interop) {
            return interop.isMemberReadable(namedCaptureGroupsMap, Strings.toJavaString(name));
        }

        public static int[] getGroupNumbers(Object namedCaptureGroupsMap, TruffleString name, InteropLibrary libMap, InteropLibrary libArray, InteropToIntNode toIntNode, Node node) {
            try {
                Object interopArray = libMap.readMember(namedCaptureGroupsMap, Strings.toJavaString(name));
                int length = (int) libArray.getArraySize(interopArray);
                int[] array = new int[length];
                for (int i = 0; i < length; i++) {
                    array[i] = toIntNode.execute(node, libArray.readArrayElement(interopArray, i));
                }
                return array;
            } catch (UnsupportedMessageException | UnknownIdentifierException | InvalidArrayIndexException e) {
                throw CompilerDirectives.shouldNotReachHere(e);
            }
        }
    }

    public static final class TRegexFlagsAccessor {

        private TRegexFlagsAccessor() {
        }

        public static Object source(Object regexFlagsObject, Node node, InteropReadStringMemberNode readSourceNode) {
            return readSourceNode.execute(node, regexFlagsObject, Props.Flags.SOURCE);
        }

        public static boolean global(Object regexFlagsObject, Node node, InteropReadBooleanMemberNode readGlobalNode) {
            return readGlobalNode.execute(node, regexFlagsObject, Props.Flags.GLOBAL);
        }

        public static boolean multiline(Object regexFlagsObject, Node node, InteropReadBooleanMemberNode readMultilineNode) {
            return readMultilineNode.execute(node, regexFlagsObject, Props.Flags.MULTILINE);
        }

        public static boolean ignoreCase(Object regexFlagsObject, Node node, InteropReadBooleanMemberNode readIgnoreCaseNode) {
            return readIgnoreCaseNode.execute(node, regexFlagsObject, Props.Flags.IGNORE_CASE);
        }

        public static boolean sticky(Object regexFlagsObject, Node node, InteropReadBooleanMemberNode readStickyNode) {
            return readStickyNode.execute(node, regexFlagsObject, Props.Flags.STICKY);
        }

        public static boolean unicode(Object regexFlagsObject, Node node, InteropReadBooleanMemberNode readUnicodeNode) {
            return readUnicodeNode.execute(node, regexFlagsObject, Props.Flags.UNICODE);
        }

        public static boolean dotAll(Object regexFlagsObject, Node node, InteropReadBooleanMemberNode readDotAllNode) {
            return readDotAllNode.execute(node, regexFlagsObject, Props.Flags.DOT_ALL);
        }

        public static boolean hasIndices(Object regexFlagsObject, Node node, InteropReadBooleanMemberNode readHasIndicesNode) {
            return readHasIndicesNode.execute(node, regexFlagsObject, Props.Flags.HAS_INDICES);
        }

        public static boolean unicodeSets(Object regexFlagsObject, Node node, InteropReadBooleanMemberNode readUnicodeSetsNode) {
            return readUnicodeSetsNode.execute(node, regexFlagsObject, Props.Flags.UNICODE_SETS);
        }
    }

    @GenerateInline
    @GenerateCached(false)
    public abstract static class TRegexCompiledRegexSingleFlagAccessorNode extends Node {

        public abstract boolean execute(Node node, Object compiledRegex, String flag);

        @Specialization
        static boolean get(Node node, Object compiledRegex, String flag,
                        @Cached InteropReadMemberNode readFlagsObjectNode,
                        @Cached InteropReadBooleanMemberNode readFlagNode) {
            CompilerAsserts.partialEvaluationConstant(flag);
            return readFlagNode.execute(node, readFlagsObjectNode.execute(node, compiledRegex, Props.CompiledRegex.FLAGS), flag);
        }
    }

    public static final class TRegexResultAccessor {

        private TRegexResultAccessor() {
        }

        public static boolean isMatch(Object result, Node node, TRegexUtil.InteropReadBooleanMemberNode readIsMatch) {
            return readIsMatch.execute(node, result, TRegexUtil.Props.RegexResult.IS_MATCH);
        }

        public static int groupCount(Object compiledRegex, Node node, TRegexUtil.InteropReadIntMemberNode readGroupCount) {
            return readGroupCount.execute(node, compiledRegex, Props.CompiledRegex.GROUP_COUNT);
        }

        public static int captureGroupStart(Object result, int groupNumber, Node node, TRegexUtil.InvokeGetGroupBoundariesMethodNode getStart) {
            return getStart.execute(node, result, TRegexUtil.Props.RegexResult.GET_START, groupNumber);
        }

        public static int captureGroupEnd(Object result, int groupNumber, Node node, TRegexUtil.InvokeGetGroupBoundariesMethodNode getEnd) {
            return getEnd.execute(node, result, TRegexUtil.Props.RegexResult.GET_END, groupNumber);
        }

        public static int captureGroupLength(Object regexResultObject, int groupNumber, Node node,
                        TRegexUtil.InvokeGetGroupBoundariesMethodNode getStart,
                        TRegexUtil.InvokeGetGroupBoundariesMethodNode getEnd) {
            return captureGroupEnd(regexResultObject, groupNumber, node, getStart) - captureGroupStart(regexResultObject, groupNumber, node, getEnd);
        }

    }

    public static final class TRegexMaterializeResult {

        private TRegexMaterializeResult() {
        }

        public static Object materializeGroupUncached(Object regexResult, int i, TruffleString input) {
            return TRegexMaterializeResult.materializeGroup(JavaScriptLanguage.get(null).getJSContext(), regexResult, i, input,
                            null, SubstringByteIndexNode.getUncached(), InvokeGetGroupBoundariesMethodNode.getUncached(), InvokeGetGroupBoundariesMethodNode.getUncached());
        }

        public static Object materializeGroupUncached(Object regexResult, int[] indices, TruffleString input) {
            return TRegexMaterializeResult.materializeGroup(JavaScriptLanguage.get(null).getJSContext(), regexResult, indices, input,
                            null, SubstringByteIndexNode.getUncached(), InvokeGetGroupBoundariesMethodNode.getUncached(), InvokeGetGroupBoundariesMethodNode.getUncached());
        }

        public static Object materializeGroup(JSContext context, Object regexResult, int i, TruffleString input,
                        Node node, TruffleString.SubstringByteIndexNode substringNode, InvokeGetGroupBoundariesMethodNode getStart, InvokeGetGroupBoundariesMethodNode getEnd) {
            final int beginIndex = TRegexResultAccessor.captureGroupStart(regexResult, i, node, getStart);
            if (beginIndex == Constants.CAPTURE_GROUP_NO_MATCH) {
                assert i > 0;
                return Undefined.instance;
            } else {
                int endIndex = TRegexResultAccessor.captureGroupEnd(regexResult, i, node, getEnd);
                return Strings.substring(context, substringNode, input, beginIndex, endIndex - beginIndex);
            }
        }

        public static Object materializeGroup(JSContext context, Object regexResult, int[] indices, TruffleString input,
                        Node node, TruffleString.SubstringByteIndexNode substringNode, InvokeGetGroupBoundariesMethodNode getStart, InvokeGetGroupBoundariesMethodNode getEnd) {
            for (int i : indices) {
                final int beginIndex = TRegexResultAccessor.captureGroupStart(regexResult, i, node, getStart);
                if (beginIndex != Constants.CAPTURE_GROUP_NO_MATCH) {
                    int endIndex = TRegexResultAccessor.captureGroupEnd(regexResult, i, node, getEnd);
                    return Strings.substring(context, substringNode, input, beginIndex, endIndex - beginIndex);
                }
            }
            return Undefined.instance;
        }

        public static Object[] materializeFull(JSContext context, Object regexResult, int groupCount, TruffleString input,
                        Node node, TruffleString.SubstringByteIndexNode substringNode, InvokeGetGroupBoundariesMethodNode getStart, InvokeGetGroupBoundariesMethodNode getEnd) {
            Object[] result = new Object[groupCount];
            for (int i = 0; i < groupCount; i++) {
                result[i] = materializeGroup(context, regexResult, i, input, node, substringNode, getStart, getEnd);
            }
            return result;
        }

        public static Object[] materializeFullUncached(Object regexResult, int groupCount, TruffleString input) {
            return materializeFull(JavaScriptLanguage.get(null).getJSContext(), regexResult, groupCount, input,
                            null, SubstringByteIndexNode.getUncached(), InvokeGetGroupBoundariesMethodNode.getUncached(), InvokeGetGroupBoundariesMethodNode.getUncached());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy