|
25 | 25 | */ |
26 | 26 | package com.oracle.graal.python.builtins.modules; |
27 | 27 |
|
| 28 | +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.EOFError; |
28 | 29 | import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RuntimeError; |
29 | 30 | import static com.oracle.graal.python.builtins.PythonBuiltinClassType.StopIteration; |
30 | 31 | import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SyntaxError; |
|
75 | 76 | import static com.oracle.graal.python.nodes.BuiltinNames.T_EVAL; |
76 | 77 | import static com.oracle.graal.python.nodes.BuiltinNames.T_EXEC; |
77 | 78 | import static com.oracle.graal.python.nodes.BuiltinNames.T_NOT_IMPLEMENTED; |
| 79 | +import static com.oracle.graal.python.nodes.BuiltinNames.T_READLINE; |
| 80 | +import static com.oracle.graal.python.nodes.BuiltinNames.T_STDERR; |
| 81 | +import static com.oracle.graal.python.nodes.BuiltinNames.T_STDIN; |
78 | 82 | import static com.oracle.graal.python.nodes.BuiltinNames.T_STDOUT; |
79 | 83 | import static com.oracle.graal.python.nodes.BuiltinNames.T_SYS; |
80 | 84 | import static com.oracle.graal.python.nodes.BuiltinNames.T___BUILTINS__; |
|
125 | 129 | import com.oracle.graal.python.builtins.objects.PNotImplemented; |
126 | 130 | import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary; |
127 | 131 | import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAcquireLibrary; |
| 132 | +import com.oracle.graal.python.builtins.objects.bytes.BytesNodes; |
128 | 133 | import com.oracle.graal.python.builtins.objects.bytes.PByteArray; |
129 | 134 | import com.oracle.graal.python.builtins.objects.bytes.PBytes; |
130 | 135 | import com.oracle.graal.python.builtins.objects.bytes.PBytesLike; |
|
167 | 172 | import com.oracle.graal.python.compiler.Compiler; |
168 | 173 | import com.oracle.graal.python.compiler.ParserCallbacksImpl; |
169 | 174 | import com.oracle.graal.python.lib.IteratorExhausted; |
| 175 | +import com.oracle.graal.python.lib.PyBytesCheckNode; |
170 | 176 | import com.oracle.graal.python.lib.PyCallableCheckNode; |
171 | 177 | import com.oracle.graal.python.lib.PyEvalGetGlobals; |
172 | 178 | import com.oracle.graal.python.lib.PyEvalGetLocals; |
|
196 | 202 | import com.oracle.graal.python.lib.PyObjectSizeNode; |
197 | 203 | import com.oracle.graal.python.lib.PyObjectStrAsObjectNode; |
198 | 204 | import com.oracle.graal.python.lib.PyObjectStrAsTruffleStringNode; |
| 205 | +import com.oracle.graal.python.lib.PyUnicodeCheckNode; |
199 | 206 | import com.oracle.graal.python.lib.PyUnicodeFSDecoderNode; |
200 | 207 | import com.oracle.graal.python.lib.RichCmpOp; |
201 | 208 | import com.oracle.graal.python.nodes.BuiltinNames; |
|
287 | 294 | import com.oracle.truffle.api.dsl.ReportPolymorphism; |
288 | 295 | import com.oracle.truffle.api.dsl.Specialization; |
289 | 296 | import com.oracle.truffle.api.dsl.TypeSystemReference; |
| 297 | +import com.oracle.truffle.api.exception.AbstractTruffleException; |
290 | 298 | import com.oracle.truffle.api.frame.Frame; |
291 | 299 | import com.oracle.truffle.api.frame.VirtualFrame; |
292 | 300 | import com.oracle.truffle.api.interop.InteropLibrary; |
@@ -2593,4 +2601,89 @@ static Object doGeneric(VirtualFrame frame, Object arg, |
2593 | 2601 | return aiter.execute(frame, arg); |
2594 | 2602 | } |
2595 | 2603 | } |
| 2604 | + |
| 2605 | + // input([prompt]) |
| 2606 | + @Builtin(name = "input", minNumOfPositionalArgs = 0, parameterNames = {"prompt"}) |
| 2607 | + @GenerateNodeFactory |
| 2608 | + abstract static class InputNode extends PythonUnaryBuiltinNode { |
| 2609 | + |
| 2610 | + @Specialization |
| 2611 | + static Object input(VirtualFrame frame, Object prompt, |
| 2612 | + @Bind Node inliningTarget, |
| 2613 | + @Bind PythonContext context, |
| 2614 | + @Cached SysModuleBuiltins.AuditNode auditNode, |
| 2615 | + @Cached PyObjectCallMethodObjArgs callMethod, |
| 2616 | + @Cached PyObjectStrAsObjectNode strNode, |
| 2617 | + @Cached PyObjectLookupAttr lookupAttr, |
| 2618 | + @Cached PyBytesCheckNode bytesCheck, |
| 2619 | + @Cached PyUnicodeCheckNode unicodeCheck, |
| 2620 | + @Cached CastToTruffleStringNode castToTruffleStringNode, |
| 2621 | + @Cached TruffleString.CodePointLengthNode codePointLengthNode, |
| 2622 | + @Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode, |
| 2623 | + @Cached TruffleString.SubstringNode substringNode, |
| 2624 | + @Cached BytesNodes.ToBytesNode toBytesNode, |
| 2625 | + @Cached PRaiseNode raiseLostNode, |
| 2626 | + @Cached PRaiseNode raiseEOFNode, |
| 2627 | + @Cached PRaiseNode raiseWrongType) { |
| 2628 | + PythonModule sysModule = context.getSysModule(); |
| 2629 | + Object stdin = lookupAttr.execute(frame, inliningTarget, sysModule, T_STDIN); |
| 2630 | + Object stdout = lookupAttr.execute(frame, inliningTarget, sysModule, T_STDOUT); |
| 2631 | + Object stderr = lookupAttr.execute(frame, inliningTarget, sysModule, T_STDERR); |
| 2632 | + |
| 2633 | + if (stdin instanceof PNone) { |
| 2634 | + throw raiseLostNode.raise(inliningTarget, RuntimeError, ErrorMessages.INPUT_LOST_SYS_S, T_STDIN); |
| 2635 | + } |
| 2636 | + if (stdout instanceof PNone) { |
| 2637 | + throw raiseLostNode.raise(inliningTarget, RuntimeError, ErrorMessages.INPUT_LOST_SYS_S, T_STDOUT); |
| 2638 | + } |
| 2639 | + if (stderr instanceof PNone) { |
| 2640 | + throw raiseLostNode.raise(inliningTarget, RuntimeError, ErrorMessages.INPUT_LOST_SYS_S, T_STDERR); |
| 2641 | + } |
| 2642 | + |
| 2643 | + auditNode.audit(inliningTarget, "builtins.input", prompt != NO_VALUE ? prompt : NONE); |
| 2644 | + |
| 2645 | + try { |
| 2646 | + callMethod.execute(frame, inliningTarget, stderr, T_FLUSH); |
| 2647 | + } catch (AbstractTruffleException e) { |
| 2648 | + // Ignore |
| 2649 | + } |
| 2650 | + |
| 2651 | + if (!(prompt instanceof PNone)) { |
| 2652 | + Object promptStr = strNode.execute(frame, inliningTarget, prompt); |
| 2653 | + callMethod.execute(frame, inliningTarget, stdout, T_WRITE, promptStr); |
| 2654 | + try { |
| 2655 | + callMethod.execute(frame, inliningTarget, stdout, T_FLUSH); |
| 2656 | + } catch (AbstractTruffleException e) { |
| 2657 | + // Ignore |
| 2658 | + } |
| 2659 | + } |
| 2660 | + |
| 2661 | + Object line = callMethod.execute(frame, inliningTarget, stdin, T_READLINE); |
| 2662 | + if (unicodeCheck.execute(inliningTarget, line)) { |
| 2663 | + TruffleString strLine = castToTruffleStringNode.castKnownString(inliningTarget, line); |
| 2664 | + int len = codePointLengthNode.execute(strLine, TS_ENCODING); |
| 2665 | + if (len == 0) { |
| 2666 | + throw raiseEOFNode.raise(inliningTarget, EOFError, ErrorMessages.EOF_WHEN_READING_A_LINE); |
| 2667 | + } |
| 2668 | + int lastChar = codePointAtIndexNode.execute(strLine, len - 1, TS_ENCODING); |
| 2669 | + if (lastChar == '\n') { |
| 2670 | + strLine = substringNode.execute(strLine, 0, len - 1, TS_ENCODING, false); |
| 2671 | + } |
| 2672 | + return strLine; |
| 2673 | + } else if (bytesCheck.execute(inliningTarget, line)) { |
| 2674 | + byte[] bytesLine = toBytesNode.execute(frame, line); |
| 2675 | + if (bytesLine.length == 0) { |
| 2676 | + throw raiseEOFNode.raise(inliningTarget, EOFError, ErrorMessages.EOF_WHEN_READING_A_LINE); |
| 2677 | + } |
| 2678 | + PythonLanguage language = context.getLanguage(inliningTarget); |
| 2679 | + if (bytesLine[bytesLine.length - 1] == '\n') { |
| 2680 | + return PFactory.createBytes(language, bytesLine, bytesLine.length - 1); |
| 2681 | + } else { |
| 2682 | + return PFactory.createBytes(language, bytesLine); |
| 2683 | + } |
| 2684 | + } else { |
| 2685 | + throw raiseWrongType.raise(inliningTarget, TypeError, ErrorMessages.OBJECT_READLINE_RETURNED_NON_STRING); |
| 2686 | + } |
| 2687 | + } |
| 2688 | + } |
2596 | 2689 | } |
0 commit comments