Skip to content

Commit e20d0ec

Browse files
author
Michal Medvecky
committed
except* implementation
# Conflicts: # graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java
1 parent 20e0ab1 commit e20d0ec

File tree

16 files changed

+1195
-36
lines changed

16 files changed

+1195
-36
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags_bytecode_dsl/test_compile.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,4 @@ test.test_compile.TestStackSizeStability.test_async_for @ linux-x86_64
4747
test.test_compile.TestStackSizeStability.test_async_for_else @ linux-x86_64
4848
test.test_compile.TestStackSizeStability.test_if @ linux-x86_64
4949
test.test_compile.TestStackSizeStability.test_if_else @ linux-x86_64
50-
test.test_compile.TestStackSizeStability.test_try_except_star_as @ linux-x86_64
51-
test.test_compile.TestStackSizeStability.test_try_except_star_finally @ linux-x86_64
52-
test.test_compile.TestStackSizeStability.test_try_except_star_qualified @ linux-x86_64
5350
test.test_compile.TestStackSizeStability.test_while_else @ linux-x86_64
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,58 @@
11
test.test_except_star.TestInvalidExceptStar.test_mixed_except_and_except_star_is_syntax_error @ linux-x86_64
2+
test.test_except_star.TestInvalidExceptStar.test_except_star_ExceptionGroup_is_runtime_error_single @ linux-x86_64
3+
test.test_except_star.TestInvalidExceptStar.test_except_star_ExceptionGroup_is_runtime_error_tuple @ linux-x86_64
4+
test.test_except_star.TestInvalidExceptStar.test_except_star_invalid_exception_type @ linux-x86_64
5+
test.test_except_star.TestBreakContinueReturnInExceptStarBlock.test_break_in_except_star @ linux-x86_64
6+
test.test_except_star.TestBreakContinueReturnInExceptStarBlock.test_continue_in_except_star_block_invalid @ linux-x86_64
7+
test.test_except_star.TestBreakContinueReturnInExceptStarBlock.test_return_in_except_star_block_invalid @ linux-x86_64
8+
test.test_except_star.TestBreakContinueReturnInExceptStarBlock.test_break_continue_in_except_star_block_valid @ linux-x86_64
9+
test.test_except_star.TestBreakContinueReturnInExceptStarBlock.test_return_in_except_star_block_valid @ linux-x86_64
10+
test.test_except_star.TestExceptStarSplitSemantics.test_empty_groups_removed @ linux-x86_64
11+
test.test_except_star.TestExceptStarSplitSemantics.test_no_match_single_type @ linux-x86_64
12+
test.test_except_star.TestExceptStarSplitSemantics.test_match_single_type @ linux-x86_64
13+
test.test_except_star.TestExceptStarSplitSemantics.test_match_single_type_partial_match @ linux-x86_64
14+
test.test_except_star.TestExceptStarSplitSemantics.test_match_single_type_nested @ linux-x86_64
15+
test.test_except_star.TestExceptStarSplitSemantics.test_match_type_tuple_nested @ linux-x86_64
16+
test.test_except_star.TestExceptStarSplitSemantics.test_singleton_groups_are_kept @ linux-x86_64
17+
test.test_except_star.TestExceptStarSplitSemantics.test_naked_exception_matched_wrapped1 @ linux-x86_64
18+
test.test_except_star.TestExceptStarSplitSemantics.test_naked_exception_matched_wrapped2 @ linux-x86_64
19+
test.test_except_star.TestExceptStarSplitSemantics.test_exception_group_except_star_Exception_not_wrapped @ linux-x86_64
20+
test.test_except_star.TestExceptStarSplitSemantics.test_plain_exception_not_matched @ linux-x86_64
21+
test.test_except_star.TestExceptStarSplitSemantics.test_match__supertype @ linux-x86_64
22+
test.test_except_star.TestExceptStarSplitSemantics.test_multiple_matches_named @ linux-x86_64
23+
test.test_except_star.TestExceptStarSplitSemantics.test_multiple_matches_unnamed @ linux-x86_64
24+
test.test_except_star.TestExceptStarSplitSemantics.test_first_match_wins_named @ linux-x86_64
25+
test.test_except_star.TestExceptStarSplitSemantics.test_first_match_wins_unnamed @ linux-x86_64
26+
test.test_except_star.TestExceptStarSplitSemantics.test_nested_except_stars @ linux-x86_64
27+
test.test_except_star.TestExceptStarSplitSemantics.test_nested_in_loop @ linux-x86_64
28+
test.test_except_star.TestExceptStarReraise.test_reraise_all_named @ linux-x86_64
29+
test.test_except_star.TestExceptStarReraise.test_reraise_all_unnamed @ linux-x86_64
30+
test.test_except_star.TestExceptStarReraise.test_reraise_some_handle_all_named @ linux-x86_64
31+
test.test_except_star.TestExceptStarReraise.test_reraise_partial_handle_all_unnamed @ linux-x86_64
32+
test.test_except_star.TestExceptStarReraise.test_reraise_partial_handle_some_named @ linux-x86_64
33+
test.test_except_star.TestExceptStarReraise.test_reraise_partial_handle_some_unnamed @ linux-x86_64
34+
test.test_except_star.TestExceptStarReraise.test_reraise_plain_exception_named @ linux-x86_64
35+
test.test_except_star.TestExceptStarReraise.test_reraise_plain_exception_unnamed @ linux-x86_64
36+
test.test_except_star.TestExceptStarRaise.test_raise_named @ linux-x86_64
37+
test.test_except_star.TestExceptStarRaise.test_raise_unnamed @ linux-x86_64
38+
test.test_except_star.TestExceptStarRaise.test_raise_handle_all_raise_one_named @ linux-x86_64
39+
test.test_except_star.TestExceptStarRaise.test_raise_handle_all_raise_one_unnamed @ linux-x86_64
40+
test.test_except_star.TestExceptStarRaise.test_raise_handle_all_raise_two_named @ linux-x86_64
41+
test.test_except_star.TestExceptStarRaise.test_raise_handle_all_raise_two_unnamed @ linux-x86_64
42+
test.test_except_star.TestExceptStarRaiseFrom.test_raise_named @ linux-x86_64
43+
test.test_except_star.TestExceptStarRaiseFrom.test_raise_unnamed @ linux-x86_64
44+
test.test_except_star.TestExceptStarRaiseFrom.test_raise_handle_all_raise_one_named @ linux-x86_64
45+
test.test_except_star.TestExceptStarRaiseFrom.test_raise_handle_all_raise_one_unnamed @ linux-x86_64
46+
test.test_except_star.TestExceptStarRaiseFrom.test_raise_handle_all_raise_two_named @ linux-x86_64
47+
test.test_except_star.TestExceptStarRaiseFrom.test_raise_handle_all_raise_two_unnamed @ linux-x86_64
48+
test.test_except_star.TestExceptStarExceptionGroupSubclass.test_falsy_exception_group_subclass @ linux-x86_64
49+
test.test_except_star.TestExceptStarExceptionGroupSubclass.test_except_star_EG_subclass @ linux-x86_64
50+
test.test_except_star.TestExceptStarCleanup.test_sys_exception_restored @ linux-x86_64
51+
test.test_except_star.TestExceptStar_WeirdLeafExceptions.test_catch_unhashable_leaf_exception @ linux-x86_64
52+
test.test_except_star.TestExceptStar_WeirdLeafExceptions.test_propagate_unhashable_leaf @ linux-x86_64
53+
test.test_except_star.TestExceptStar_WeirdLeafExceptions.test_catch_nothing_unhashable_leaf @ linux-x86_64
54+
test.test_except_star.TestExceptStar_WeirdLeafExceptions.test_catch_everything_unhashable_leaf @ linux-x86_64
55+
test.test_except_star.TestExceptStar_WeirdLeafExceptions.test_reraise_unhashable_leaf @ linux-x86_64
56+
test.test_except_star.TestExceptStar_WeirdExceptionGroupSubclass.test_catch_some_unhashable_exception_group_subclass @ linux-x86_64
57+
test.test_except_star.TestExceptStar_WeirdExceptionGroupSubclass.test_catch_none_unhashable_exception_group_subclass @ linux-x86_64
58+
test.test_except_star.TestExceptStar_WeirdExceptionGroupSubclass.test_catch_all_unhashable_exception_group_subclass @ linux-x86_64

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/BaseExceptionGroupBuiltins.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,11 @@ private static void createExceptionGroupType(Python3Core core) {
143143
@SlotSignature(name = "BaseExceptionGroup.__new__", minNumOfPositionalArgs = 3)
144144
@GenerateNodeFactory
145145
public abstract static class BaseExceptionGroupNode extends PythonTernaryBuiltinNode {
146+
@Override
147+
public abstract PBaseExceptionGroup execute(VirtualFrame frame, Object cls, Object messageObj, Object exceptionsObj);
146148

147149
@Specialization
148-
static Object doManaged(VirtualFrame frame, Object cls, Object messageObj, Object exceptionsObj,
150+
static PBaseExceptionGroup doManaged(VirtualFrame frame, Object cls, Object messageObj, Object exceptionsObj,
149151
@Bind Node inliningTarget,
150152
@Bind PythonLanguage language,
151153
@Cached TypeNodes.GetInstanceShape getInstanceShape,
@@ -233,6 +235,7 @@ static TruffleString str(PBaseExceptionGroup self,
233235
appendCodePointNode.execute(builder, 's');
234236
}
235237
appendCodePointNode.execute(builder, ')');
238+
// TODO: GR-70916 recursive printing of exception groups + indentation
236239
return toStringNode.execute(builder);
237240
}
238241
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/ChainExceptionsNode.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,44 @@
4848
import com.oracle.truffle.api.dsl.NeverDefault;
4949
import com.oracle.truffle.api.dsl.Specialization;
5050
import com.oracle.truffle.api.nodes.Node;
51+
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
5152
import com.oracle.truffle.api.profiles.InlinedLoopConditionProfile;
5253

5354
@GenerateInline(false) // Used in BCI
5455
public abstract class ChainExceptionsNode extends Node {
5556
public abstract void execute(PException currentException, PException contextException);
5657

58+
private static boolean compare(PBaseExceptionGroup currentGroup, PBaseExceptionGroup contextGroup, Node inliningTarget, InlinedConditionProfile conditionProfile) {
59+
return conditionProfile.profile(
60+
inliningTarget,
61+
currentGroup != contextGroup && ((currentGroup.getParent() == null || contextGroup.getParent() == null) || currentGroup.getParent() != contextGroup.getParent()));
62+
}
63+
5764
@Specialization
5865
public static void chainExceptions(PException currentException, PException contextException,
5966
@Bind Node inliningTarget,
6067
@Cached ExceptionNodes.GetContextNode getContextNode,
6168
@Cached ExceptionNodes.SetContextNode setContextNode,
6269
@Cached InlinedLoopConditionProfile p1,
63-
@Cached InlinedLoopConditionProfile p2) {
70+
@Cached InlinedLoopConditionProfile p2,
71+
@Cached InlinedConditionProfile areExceptionGroups,
72+
@Cached InlinedConditionProfile compareCurrentAndContext) {
6473
Object current = currentException.getUnreifiedException();
6574
Object context = contextException.getUnreifiedException();
66-
if (current != context) {
75+
boolean shouldChain = false;
76+
boolean checkAreExceptionGroups = areExceptionGroups.profile(
77+
inliningTarget,
78+
current instanceof PBaseExceptionGroup && context instanceof PBaseExceptionGroup);
79+
if (checkAreExceptionGroups) {
80+
// for exception groups, the check needs to be done for parent, and not the original,
81+
// since some exceptions may be filtered out from `current` when evaluating the except*
82+
// match
83+
shouldChain = compare((PBaseExceptionGroup) current, (PBaseExceptionGroup) context, inliningTarget, compareCurrentAndContext);
84+
} else if (compareCurrentAndContext.profile(inliningTarget, current != context)) {
85+
shouldChain = true;
86+
}
87+
88+
if (shouldChain) {
6789
Object e = current;
6890
while (p1.profile(inliningTarget, e != PNone.NONE)) {
6991
Object eContext = getContextNode.execute(inliningTarget, e);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/PBaseExceptionGroup.java

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -41,12 +41,33 @@
4141
package com.oracle.graal.python.builtins.objects.exception;
4242

4343
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
44+
import com.oracle.graal.python.runtime.exception.PException;
45+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
4446
import com.oracle.truffle.api.object.Shape;
4547
import com.oracle.truffle.api.strings.TruffleString;
4648

4749
public class PBaseExceptionGroup extends PBaseException {
4850
private final TruffleString message;
4951
private final Object[] exceptions;
52+
@CompilationFinal private PException parent; // effectively final
53+
54+
/**
55+
* Flag to denote if the `exceptions` field contains only reraised and/or unmatched exceptions.
56+
*/
57+
@CompilationFinal private boolean containsReraises; // effectively final
58+
59+
/**
60+
* This flag marks the outer/final exception group that encompasses all other exception groups
61+
* that are thrown at the end of the try-except* block. This is needed, since we can nest other
62+
* exception groups into exception groups themselves.
63+
*/
64+
@CompilationFinal private boolean isOuter; // effectively final
65+
66+
/**
67+
* Context setting behaves somewhat differently when handling exception groups. This flag
68+
* assures, that context, after being once set, won't be set again/overwritten.
69+
*/
70+
@CompilationFinal private boolean contextWasExplicitlySet; // effectively final
5071

5172
public PBaseExceptionGroup(Object cls, Shape instanceShape, TruffleString message, Object[] exceptions, PTuple args) {
5273
super(cls, instanceShape, null, args);
@@ -61,4 +82,59 @@ public Object[] getExceptions() {
6182
public TruffleString getMessage() {
6283
return message;
6384
}
85+
86+
public void setParent(PException parent) {
87+
this.parent = parent;
88+
}
89+
90+
public PException getParent() {
91+
return this.parent;
92+
}
93+
94+
/**
95+
* See {@link PBaseExceptionGroup#containsReraises}
96+
*/
97+
public void setContainsReraises(boolean value) {
98+
this.containsReraises = value;
99+
}
100+
101+
/**
102+
* See {@link PBaseExceptionGroup#containsReraises}
103+
*/
104+
public boolean getContainsReraises() {
105+
return this.containsReraises;
106+
}
107+
108+
/**
109+
* See {@link PBaseExceptionGroup#isOuter}
110+
*/
111+
public void setIsOuter(boolean value) {
112+
this.isOuter = value;
113+
}
114+
115+
/**
116+
* See {@link PBaseExceptionGroup#isOuter}
117+
*/
118+
public boolean getIsOuter() {
119+
return this.isOuter;
120+
}
121+
122+
/**
123+
* See {@link PBaseExceptionGroup#contextWasExplicitlySet}
124+
*/
125+
public void setContextExplicitly(Object context) {
126+
contextWasExplicitlySet = true;
127+
super.setContext(context);
128+
}
129+
130+
/**
131+
* See also {@link PBaseExceptionGroup#setContextExplicitly} and
132+
* {@link PBaseExceptionGroup#contextWasExplicitlySet}
133+
*/
134+
public void setContext(Object context) {
135+
if (contextWasExplicitlySet) {
136+
return;
137+
}
138+
super.setContext(context);
139+
}
64140
}

0 commit comments

Comments
 (0)