Skip to content

Commit c86bd0d

Browse files
committed
Implement CoerceToFileDescriptorNode.
1 parent 102edfe commit c86bd0d

File tree

2 files changed

+143
-1
lines changed

2 files changed

+143
-1
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2020, 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
@@ -164,6 +164,7 @@ public abstract class SpecialMethodNames {
164164
public static final String DECODE = "decode";
165165
public static final String __SIZEOF__ = "__sizeof__";
166166
public static final String __CLASS_GETITEM__ = "__class_getitem__";
167+
public static final String FILENO = "fileno";
167168

168169
public static final String RICHCMP = "__truffle_richcompare__";
169170
public static final String TRUFFLE_SOURCE = "__truffle_source__";
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.nodes.util;
42+
43+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
44+
import com.oracle.graal.python.builtins.objects.PNone;
45+
import com.oracle.graal.python.builtins.objects.ints.PInt;
46+
import com.oracle.graal.python.nodes.PNodeWithContext;
47+
import com.oracle.graal.python.nodes.PRaiseNode;
48+
import com.oracle.graal.python.nodes.SpecialMethodNames;
49+
import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetFixedAttributeNode;
50+
import com.oracle.graal.python.nodes.call.CallNode;
51+
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
52+
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
53+
import com.oracle.graal.python.runtime.exception.PException;
54+
import com.oracle.truffle.api.dsl.Cached;
55+
import com.oracle.truffle.api.dsl.Cached.Exclusive;
56+
import com.oracle.truffle.api.dsl.Cached.Shared;
57+
import com.oracle.truffle.api.dsl.Specialization;
58+
import com.oracle.truffle.api.frame.VirtualFrame;
59+
import com.oracle.truffle.api.profiles.BranchProfile;
60+
61+
/**
62+
* Coerces a given primitive or object to a file descriptor (i.e. Java {@code int}). This node
63+
* follows the semantics of CPython's function {@code PyObject_AsFileDescriptor}.
64+
*/
65+
public abstract class CoerceToFileDescriptorNode extends PNodeWithContext {
66+
67+
private static final String ERROR_MESSAGE = "Python int too large to convert to int";
68+
69+
public abstract int execute(VirtualFrame frame, Object x);
70+
71+
public abstract int executeInt(VirtualFrame frame, int x);
72+
73+
public abstract int executeLong(VirtualFrame frame, long x);
74+
75+
@Specialization
76+
static int doInt(int x) {
77+
return x;
78+
}
79+
80+
@Specialization(replaces = "doInt")
81+
static int doLong(long x,
82+
@Shared("raiseNode") @Cached PRaiseNode raiseNode,
83+
@Exclusive @Cached CastToJavaIntNode castToJavaIntNode) {
84+
try {
85+
return castToJavaIntNode.execute(x);
86+
} catch (PException e) {
87+
// we need to convert the TypeError to an OverflowError
88+
throw raiseNode.raise(PythonBuiltinClassType.OverflowError, ERROR_MESSAGE);
89+
}
90+
}
91+
92+
@Specialization(replaces = {"doInt", "doLong"})
93+
static int doPInt(PInt x,
94+
@Shared("raiseNode") @Cached PRaiseNode raiseNode,
95+
@Exclusive @Cached CastToJavaIntNode castToJavaIntNode) {
96+
try {
97+
return castToJavaIntNode.execute(x);
98+
} catch (PException e) {
99+
throw raiseNode.raise(PythonBuiltinClassType.OverflowError, ERROR_MESSAGE);
100+
}
101+
}
102+
103+
@Specialization(replaces = {"doInt", "doLong", "doPInt"})
104+
static int doGeneric(VirtualFrame frame, Object x,
105+
@Exclusive @Cached CastToJavaIntNode castToJavaIntNode,
106+
@Cached("createFileno()") GetFixedAttributeNode getFixedAttributeNode,
107+
@Cached BranchProfile noFilenoMethodProfile,
108+
@Cached CallNode callFilenoNode,
109+
@Cached GetLazyClassNode getClassNode,
110+
@Cached IsBuiltinClassProfile isIntProfile,
111+
@Shared("raiseNode") @Cached PRaiseNode raiseNode) {
112+
try {
113+
if (x instanceof Integer || x instanceof Long || x instanceof PInt) {
114+
return castToJavaIntNode.execute(x);
115+
}
116+
} catch (PException e) {
117+
throw raiseNode.raise(PythonBuiltinClassType.OverflowError, ERROR_MESSAGE);
118+
}
119+
120+
Object attrFileno = getFixedAttributeNode.executeObject(frame, x);
121+
if (attrFileno == PNone.NO_VALUE) {
122+
noFilenoMethodProfile.enter();
123+
throw raiseNode.raise(PythonBuiltinClassType.TypeError, "argument must be an int, or have a fileno() method.");
124+
}
125+
126+
Object result = callFilenoNode.execute(frame, attrFileno);
127+
if (isIntProfile.profileClass(getClassNode.execute(result), PythonBuiltinClassType.PInt)) {
128+
try {
129+
return castToJavaIntNode.execute(result);
130+
} catch (PException e) {
131+
throw raiseNode.raise(PythonBuiltinClassType.OverflowError, ERROR_MESSAGE);
132+
}
133+
} else {
134+
throw raiseNode.raise(PythonBuiltinClassType.TypeError, "fileno() returned a non-integer");
135+
}
136+
}
137+
138+
static GetFixedAttributeNode createFileno() {
139+
return GetFixedAttributeNode.create(SpecialMethodNames.FILENO);
140+
}
141+
}

0 commit comments

Comments
 (0)