Skip to content

Commit 17b132f

Browse files
committed
[GR-14968] Fix issues around regex, pygments, and loop breaks and add tests
PullRequest: graalpython/473
2 parents 3f9ada8 + a814484 commit 17b132f

File tree

12 files changed

+152
-137
lines changed

12 files changed

+152
-137
lines changed

graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ protected List<String> preprocessArguments(List<String> givenArgs, Map<String, S
189189
subprocessArgs.add("Dgraal.TruffleCompilationExceptionsArePrinted=true");
190190
subprocessArgs.add("Dgraal.TraceTruffleInlining=true");
191191
subprocessArgs.add("Dgraal.TruffleTraceSplittingSummary=true");
192+
subprocessArgs.add("Dgraal.TraceTruffleTransferToInterpreter=true");
193+
subprocessArgs.add("Dgraal.TraceTruffleAssumptions=true");
192194
inputArgs.remove("-debug-perf");
193195
} else {
194196
unrecognized.add(arg);

graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,8 +688,8 @@ def test_translate_no_change(self):
688688

689689
class ByteArrayTest(BaseLikeBytes, unittest.TestCase):
690690
type2test = bytearray
691-
692-
def test_translate_no_change(self):
691+
692+
def test_translate_no_change2(self):
693693
b = bytearray(b'ahoj')
694694
self.assertIsNot(b, b.translate(None))
695695
self.assertIsNot(b, b.translate(None, b''))

graalpython/com.oracle.graal.python.test/src/tests/test_for.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -86,3 +86,29 @@ def test_else_continue():
8686
continue
8787

8888
assert ["continue", "break"] == sequence
89+
90+
91+
def test_else_break():
92+
iters = 0
93+
while iters < 4:
94+
for i in range(iters):
95+
if False:
96+
break
97+
iters += 1
98+
else:
99+
iters += 1
100+
break
101+
assert iters == 1, "if the for-loop doesn't break, the else should be executed and break out of the outer loop"
102+
103+
104+
def test_else_break_from_while():
105+
iters = 0
106+
while iters < 40:
107+
while iters < 10:
108+
if False:
109+
break
110+
iters += 1
111+
else:
112+
iters += 1
113+
break
114+
assert iters == 11, "if the while-loop doesn't break, the else should be executed and break out of the outer loop"

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/builtins/objects/bytes/AbstractBytesBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ public PByteArray translate(PByteArray self, @SuppressWarnings("unused") PNone t
932932
return factory().createByteArray(self.getSequenceStorage().copy());
933933
}
934934

935-
@Specialization
935+
@Specialization(guards = "!isNone(table)")
936936
public PBytes translate(PBytes self, Object table, @SuppressWarnings("unused") PNone delete) {
937937
byte[] bTable = getToBytesNode().execute(table);
938938
checkLengthOfTable(bTable);
@@ -945,7 +945,7 @@ public PBytes translate(PBytes self, Object table, @SuppressWarnings("unused") P
945945
return self;
946946
}
947947

948-
@Specialization
948+
@Specialization(guards = "!isNone(table)")
949949
public PByteArray translate(PByteArray self, Object table, @SuppressWarnings("unused") PNone delete) {
950950
byte[] bTable = getToBytesNode().execute(table);
951951
checkLengthOfTable(bTable);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/ByteArrayBuiltins.java

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -633,55 +633,6 @@ private int getLength(SequenceStorage s) {
633633
}
634634
}
635635

636-
@Builtin(name = "translate", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3)
637-
@GenerateNodeFactory
638-
abstract static class TranslateNode extends PythonBuiltinNode {
639-
640-
@Child private SequenceStorageNodes.GetItemNode getSelfItemNode;
641-
@Child private SequenceStorageNodes.GetItemNode getTableItemNode;
642-
643-
@Specialization
644-
PByteArray translate(PByteArray self, PBytes table, @SuppressWarnings("unused") PNone delete) {
645-
return translate(self.getSequenceStorage(), table.getSequenceStorage());
646-
}
647-
648-
@Specialization
649-
PByteArray translate(PByteArray self, PByteArray table, @SuppressWarnings("unused") PNone delete) {
650-
return translate(self.getSequenceStorage(), table.getSequenceStorage());
651-
}
652-
653-
private PByteArray translate(SequenceStorage selfStorage, SequenceStorage tableStorage) {
654-
if (tableStorage.length() != 256) {
655-
throw raise(ValueError, "translation table must be 256 characters long");
656-
}
657-
byte[] result = new byte[selfStorage.length()];
658-
for (int i = 0; i < selfStorage.length(); i++) {
659-
int b = getGetSelfItemNode().executeInt(selfStorage, i);
660-
int t = getGetTableItemNode().executeInt(tableStorage, b);
661-
assert t >= 0 && t < 256;
662-
result[i] = (byte) t;
663-
}
664-
return factory().createByteArray(result);
665-
}
666-
667-
private SequenceStorageNodes.GetItemNode getGetSelfItemNode() {
668-
if (getSelfItemNode == null) {
669-
CompilerDirectives.transferToInterpreterAndInvalidate();
670-
getSelfItemNode = insert(SequenceStorageNodes.GetItemNode.create());
671-
}
672-
return getSelfItemNode;
673-
}
674-
675-
private SequenceStorageNodes.GetItemNode getGetTableItemNode() {
676-
if (getTableItemNode == null) {
677-
CompilerDirectives.transferToInterpreterAndInvalidate();
678-
getTableItemNode = insert(SequenceStorageNodes.GetItemNode.create());
679-
}
680-
return getTableItemNode;
681-
}
682-
683-
}
684-
685636
@Builtin(name = __GETITEM__, minNumOfPositionalArgs = 2)
686637
@GenerateNodeFactory
687638
abstract static class GetitemNode extends PythonBinaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PyUnicodeWrappers.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import com.oracle.graal.python.builtins.objects.cext.DynamicObjectNativeWrapper.ToPyObjectNode;
4848
import com.oracle.graal.python.builtins.objects.cext.UnicodeObjectNodes.UnicodeAsWideCharNode;
4949
import com.oracle.graal.python.builtins.objects.str.PString;
50-
import com.oracle.truffle.api.CompilerDirectives;
5150
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
5251
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
5352
import com.oracle.truffle.api.dsl.Cached;
@@ -226,12 +225,16 @@ protected Object readMember(String member,
226225

227226
private boolean onlyAscii(String value) {
228227
if (asciiEncoder == null) {
229-
CompilerDirectives.transferToInterpreterAndInvalidate();
230-
asciiEncoder = Charset.forName("US-ASCII").newEncoder();
228+
asciiEncoder = newAsciiEncoder();
231229
}
232230
return doCheck(value, asciiEncoder);
233231
}
234232

233+
@TruffleBoundary
234+
private static CharsetEncoder newAsciiEncoder() {
235+
return Charset.forName("US-ASCII").newEncoder();
236+
}
237+
235238
@TruffleBoundary
236239
private static boolean doCheck(String value, CharsetEncoder asciiEncoder) {
237240
return asciiEncoder.canEncode(value);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/NodeFactory.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,11 @@ public StatementNode createContinueTarget(StatementNode child) {
209209
}
210210

211211
public StatementNode createBreakTarget(StatementNode forNode) {
212-
return new BreakTargetNode(forNode);
212+
return new BreakTargetNode(forNode, null);
213+
}
214+
215+
public StatementNode createBreakTarget(StatementNode forNode, StatementNode orelse) {
216+
return new BreakTargetNode(forNode, orelse);
213217
}
214218

215219
public YieldNode createYield(ExpressionNode right, FrameSlot returnSlot) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/BreakTargetNode.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -36,9 +36,11 @@ public final class BreakTargetNode extends StatementNode {
3636
private final BranchProfile defaultExitProfile = BranchProfile.create();
3737

3838
@Child private StatementNode statement;
39+
@Child private StatementNode orelse;
3940

40-
public BreakTargetNode(StatementNode statement) {
41+
public BreakTargetNode(StatementNode statement, StatementNode orelse) {
4142
this.statement = statement;
43+
this.orelse = orelse;
4244
}
4345

4446
public StatementNode getStatement() {
@@ -52,6 +54,10 @@ public void executeVoid(VirtualFrame frame) {
5254
defaultExitProfile.enter();
5355
} catch (BreakException ex) {
5456
breakProfile.enter();
57+
return;
58+
}
59+
if (orelse != null) {
60+
orelse.executeVoid(frame);
5561
}
5662
}
5763
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,15 +1255,17 @@ private PNode createWhileNode(PNode test, StatementNode body, StatementNode orel
12551255
StatementNode whileNode = factory.createWhile(factory.toBooleanCastNode(test), wrappedBody);
12561256
// assignSourceFromNode(node, whileNode);
12571257

1258-
if (!EmptyNode.isEmpty(orelse)) {
1258+
if (info.hasBreak()) {
1259+
if (!EmptyNode.isEmpty(orelse)) {
1260+
whileNode = factory.createBreakTarget(whileNode, orelse);
1261+
} else {
1262+
whileNode = factory.createBreakTarget(whileNode);
1263+
}
1264+
} else if (!EmptyNode.isEmpty(orelse)) {
12591265
whileNode = factory.createElse(whileNode, orelse);
12601266
}
12611267

1262-
if (info.hasBreak()) {
1263-
return factory.createBreakTarget(whileNode);
1264-
} else {
1265-
return whileNode;
1266-
}
1268+
return whileNode;
12671269
}
12681270

12691271
@Override
@@ -1288,15 +1290,17 @@ private StatementNode createForNode(StatementNode target, ExpressionNode iter, S
12881290
StatementNode forNode = createForInScope(target, iter, wrappedBody);
12891291
// assignSourceFromNode(node, forNode);
12901292

1291-
if (!EmptyNode.isEmpty(orelse)) {
1293+
if (info.hasBreak()) {
1294+
if (!EmptyNode.isEmpty(orelse)) {
1295+
forNode = factory.createBreakTarget(forNode, orelse);
1296+
} else {
1297+
forNode = factory.createBreakTarget(forNode);
1298+
}
1299+
} else if (!EmptyNode.isEmpty(orelse)) {
12921300
forNode = factory.createElse(forNode, orelse);
12931301
}
12941302

1295-
if (info.hasBreak()) {
1296-
return factory.createBreakTarget(forNode);
1297-
} else {
1298-
return forNode;
1299-
}
1303+
return forNode;
13001304
}
13011305

13021306
private LoopNode createForInScope(StatementNode target, ExpressionNode iterator, StatementNode body) {

0 commit comments

Comments
 (0)