Skip to content

Commit 5211779

Browse files
committed
add option to disable TRegex, fix a few code style issues in _sre.py
1 parent 2a862b0 commit 5211779

File tree

3 files changed

+71
-62
lines changed

3 files changed

+71
-62
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SREModuleBuiltins.java

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,17 @@
4040
*/
4141
package com.oracle.graal.python.builtins.modules;
4242

43-
import static com.oracle.graal.python.runtime.exception.PythonErrorType.RuntimeError;
4443
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
4544
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
4645

4746
import java.io.UnsupportedEncodingException;
4847
import java.util.List;
4948

49+
import com.oracle.graal.python.PythonLanguage;
5050
import com.oracle.graal.python.builtins.Builtin;
5151
import com.oracle.graal.python.builtins.CoreFunctions;
5252
import com.oracle.graal.python.builtins.PythonBuiltins;
53+
import com.oracle.graal.python.builtins.objects.PNone;
5354
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
5455
import com.oracle.graal.python.builtins.objects.bytes.BytesUtils;
5556
import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike;
@@ -60,20 +61,21 @@
6061
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
6162
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
6263
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
64+
import com.oracle.graal.python.runtime.PythonContext;
6365
import com.oracle.graal.python.runtime.exception.PythonErrorType;
6466
import com.oracle.truffle.api.CompilerAsserts;
6567
import com.oracle.truffle.api.CompilerDirectives;
6668
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
6769
import com.oracle.truffle.api.TruffleException;
6870
import com.oracle.truffle.api.dsl.Cached;
71+
import com.oracle.truffle.api.dsl.CachedContext;
6972
import com.oracle.truffle.api.dsl.Fallback;
7073
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
7174
import com.oracle.truffle.api.dsl.NodeFactory;
7275
import com.oracle.truffle.api.dsl.Specialization;
7376
import com.oracle.truffle.api.dsl.TypeSystemReference;
7477
import com.oracle.truffle.api.interop.ArityException;
7578
import com.oracle.truffle.api.interop.InteropLibrary;
76-
import com.oracle.truffle.api.interop.TruffleObject;
7779
import com.oracle.truffle.api.interop.UnsupportedMessageException;
7880
import com.oracle.truffle.api.interop.UnsupportedTypeException;
7981
import com.oracle.truffle.api.library.CachedLibrary;
@@ -90,9 +92,16 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
9092
@Builtin(name = "_build_regex_engine", minNumOfPositionalArgs = 1)
9193
@GenerateNodeFactory
9294
abstract static class BuildRegexEngine extends PythonUnaryBuiltinNode {
93-
@Specialization
95+
@Specialization(guards = "!getFlag(context, WithTRegex)")
96+
Object useSRE(@SuppressWarnings("unused") String code,
97+
@SuppressWarnings("unused") @CachedContext(PythonLanguage.class) PythonContext context) {
98+
return PNone.NONE;
99+
}
100+
101+
@Specialization(guards = "getFlag(context, WithTRegex)")
94102
@TruffleBoundary
95-
Object run(String code) {
103+
Object run(String code,
104+
@SuppressWarnings("unused") @CachedContext(PythonLanguage.class) PythonContext context) {
96105
return getContext().getEnv().parse(Source.newBuilder("regex", code, "build-regex-engine").build()).call();
97106
}
98107
}
@@ -188,8 +197,8 @@ private BytesNodes.ToBytesNode getToBytesNode() {
188197
@GenerateNodeFactory
189198
abstract static class TRegexCallCompile extends PythonTernaryBuiltinNode {
190199

191-
@Specialization(guards = "isForeignObject(callable)", limit = "1")
192-
Object call(TruffleObject callable, Object arg1, Object arg2,
200+
@Specialization(limit = "1")
201+
Object call(Object callable, Object arg1, Object arg2,
193202
@Cached("create()") BranchProfile syntaxError,
194203
@Cached("create()") BranchProfile typeError,
195204
@CachedLibrary("callable") InteropLibrary interop) {
@@ -207,21 +216,15 @@ Object call(TruffleObject callable, Object arg1, Object arg2,
207216
throw e;
208217
}
209218
}
210-
211-
@SuppressWarnings("unused")
212-
@Fallback
213-
Object call(Object callable, Object arg1, Object arg2) {
214-
throw raise(RuntimeError, "invalid arguments passed to tregex_call_compile");
215-
}
216219
}
217220

218221
@Builtin(name = "tregex_call_exec", minNumOfPositionalArgs = 3)
219222
@TypeSystemReference(PythonArithmeticTypes.class)
220223
@GenerateNodeFactory
221224
abstract static class TRegexCallExec extends PythonTernaryBuiltinNode {
222225

223-
@Specialization(guards = "isForeignObject(callable)", limit = "1")
224-
Object call(TruffleObject callable, Object arg1, Number arg2,
226+
@Specialization(limit = "1")
227+
Object call(Object callable, Object arg1, Number arg2,
225228
@Cached("create()") BranchProfile typeError,
226229
@CachedLibrary("callable") InteropLibrary interop) {
227230
try {
@@ -231,11 +234,5 @@ Object call(TruffleObject callable, Object arg1, Number arg2,
231234
throw raise(TypeError, "%s", e);
232235
}
233236
}
234-
235-
@SuppressWarnings("unused")
236-
@Fallback
237-
Object call(Object callable, Object arg1, Object arg2) {
238-
throw raise(RuntimeError, "invalid arguments passed to tregex_call_exec");
239-
}
240237
}
241238
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ private PythonOptions() {
130130
@Option(category = OptionCategory.EXPERT, help = "This option control builtin _thread module support") //
131131
public static final OptionKey<Boolean> WithThread = new OptionKey<>(false);
132132

133+
@Option(category = OptionCategory.EXPERT, help = "Use the optimized TRegex engine and call the CPython sre engine only as a fallback. Default true") //
134+
public static final OptionKey<Boolean> WithTRegex = new OptionKey<>(true);
135+
133136
@Option(category = OptionCategory.EXPERT, help = "Switch on/off using lazy strings for performance reasons. Default true.") //
134137
public static final OptionKey<Boolean> LazyStrings = new OptionKey<>(true);
135138

graalpython/lib-graalpython/_sre.py

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
3939

40-
import polyglot as _interop
41-
4240
from mmap import mmap
4341

4442
_mappingpoxy = type(type.__dict__)
@@ -81,6 +79,40 @@ def setup(sre_compiler, error_class, flags_table):
8179
FLAGS = flags_table
8280

8381
def configure_fallback_compiler(mode):
82+
# wraps a native 're.Pattern' object
83+
class ExecutablePattern:
84+
def __init__(self, sticky, compiled_pattern):
85+
self.__sticky__ = sticky
86+
self.__compiled_pattern__ = compiled_pattern
87+
88+
def __call__(self, *args):
89+
# deprecated
90+
return self.exec(*args)
91+
92+
def exec(self, *args):
93+
nargs = len(args)
94+
if nargs == 2:
95+
# new-style signature
96+
pattern_input, from_index = args
97+
elif nargs == 3:
98+
# old-style signature; deprecated
99+
_, pattern_input, from_index = args
100+
else:
101+
raise TypeError("invalid arguments: " + repr(args))
102+
if self.__sticky__:
103+
result = self.__compiled_pattern__.match(pattern_input, from_index)
104+
else:
105+
result = self.__compiled_pattern__.search(pattern_input, from_index)
106+
is_match = result is not None
107+
group_count = 1 + self.__compiled_pattern__.groups
108+
return _RegexResult(
109+
pattern_input = pattern_input,
110+
isMatch = is_match,
111+
groupCount = group_count if is_match else 0,
112+
start = [result.start(i) for i in range(group_count)] if is_match else [],
113+
end = [result.end(i) for i in range(group_count)] if is_match else []
114+
)
115+
84116
def fallback_compiler(pattern, flags):
85117
sticky = False
86118
bit_flags = 0
@@ -93,53 +125,30 @@ def fallback_compiler(pattern, flags):
93125

94126
compiled_pattern = sre_compiler(pattern if mode == "str" else _str_to_bytes(pattern), bit_flags)
95127

96-
# wraps a native 're.Pattern' object
97-
class ExecutablePattern:
98-
def __call__(self, *args):
99-
# deprecated
100-
return self.exec(*args)
101-
102-
def exec(self, *args):
103-
nargs = len(args)
104-
if nargs == 2:
105-
# new-style signature
106-
pattern_input, from_index = args
107-
elif nargs == 3:
108-
# old-style signature; deprecated
109-
_, pattern_input, from_index = args
110-
else:
111-
raise TypeError("invalid arguments: " + repr(args))
112-
search_method = compiled_pattern.match if sticky else compiled_pattern.search
113-
result = search_method(pattern_input, from_index)
114-
is_match = result is not None
115-
group_count = 1 + compiled_pattern.groups
116-
return _RegexResult(
117-
pattern_input = pattern_input,
118-
isMatch = is_match,
119-
groupCount = group_count if is_match else 0,
120-
start = [result.start(i) for i in range(group_count)] if is_match else [],
121-
end = [result.end(i) for i in range(group_count)] if is_match else []
122-
)
123-
124-
return ExecutablePattern()
128+
return ExecutablePattern(sticky, compiled_pattern)
125129

126130
return fallback_compiler
127131

128132
engine_builder = _build_regex_engine("")
129133

130-
global TREGEX_ENGINE_STR
131-
global TREGEX_ENGINE_BYTES
132-
TREGEX_ENGINE_STR = engine_builder("Flavor=PythonStr", configure_fallback_compiler("str"))
133-
TREGEX_ENGINE_BYTES = engine_builder("Flavor=PythonBytes", configure_fallback_compiler("bytes"))
134+
if engine_builder:
135+
global TREGEX_ENGINE_STR
136+
global TREGEX_ENGINE_BYTES
137+
TREGEX_ENGINE_STR = engine_builder("Flavor=PythonStr", configure_fallback_compiler("str"))
138+
TREGEX_ENGINE_BYTES = engine_builder("Flavor=PythonBytes", configure_fallback_compiler("bytes"))
134139

135-
def new_compile(p, flags=0):
136-
if isinstance(p, (str, bytes)):
137-
return _tcompile(p, flags)
138-
else:
140+
def new_compile(p, flags=0):
141+
if isinstance(p, (str, bytes)):
142+
return _tcompile(p, flags)
143+
else:
144+
return sre_compiler(p, flags)
145+
else:
146+
def new_compile(p, flags=0):
139147
return sre_compiler(p, flags)
140148

141149
return new_compile
142150

151+
143152
CODESIZE = 4
144153

145154
MAGIC = 20171005
@@ -196,8 +205,8 @@ def __group__(self, idx):
196205
def groupdict(self, default=None):
197206
d = {}
198207
if self.compiled_regex.groups:
199-
assert _interop.__has_keys__(self.compiled_regex.groups)
200-
for k in _interop.__keys__(self.compiled_regex.groups):
208+
assert dir(self.compiled_regex.groups)
209+
for k in dir(self.compiled_regex.groups):
201210
idx = self.compiled_regex.groups[k]
202211
d[k] = self.__group__(idx)
203212
return d
@@ -250,7 +259,7 @@ def __init__(self, pattern, flags):
250259
if self.__tregex_compile(self.pattern).groups is not None:
251260
for group_name in dir(self.__tregex_compile(self.pattern).groups):
252261
groups = self.__tregex_compile(self.pattern).groups
253-
self.groups = _interop.__get_size__(_interop.__keys__(groups))
262+
self.groups = len(dir(groups))
254263
groupindex[group_name] = groups[group_name]
255264
self.groupindex = _mappingpoxy(groupindex)
256265

0 commit comments

Comments
 (0)