Skip to content

Commit 823cde7

Browse files
committed
Implement "single" mode for bytecode
1 parent 52fdc80 commit 823cde7

File tree

8 files changed

+136
-16
lines changed

8 files changed

+136
-16
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/compiler/CompilerTests.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@
5555
import com.oracle.graal.python.compiler.CompilationUnit;
5656
import com.oracle.graal.python.compiler.Compiler;
5757
import com.oracle.graal.python.pegparser.FExprParser;
58+
import com.oracle.graal.python.pegparser.InputType;
5859
import com.oracle.graal.python.pegparser.NodeFactory;
5960
import com.oracle.graal.python.pegparser.NodeFactoryImp;
6061
import com.oracle.graal.python.pegparser.Parser;
61-
import com.oracle.graal.python.pegparser.ParserErrorCallback;
6262
import com.oracle.graal.python.pegparser.ParserTokenizer;
6363
import com.oracle.graal.python.pegparser.sst.ExprTy;
6464
import com.oracle.graal.python.pegparser.sst.ModTy;
@@ -703,24 +703,32 @@ public void testImportStar() {
703703
doTest("from a.b import *");
704704
}
705705

706+
@Test
707+
public void testEval() {
708+
doTest("1", InputType.EVAL);
709+
}
710+
711+
@Test
712+
public void testSingle() {
713+
doTest("1", InputType.SINGLE);
714+
}
715+
706716
private void doTest(String src) {
717+
doTest(src, InputType.FILE);
718+
}
719+
720+
private void doTest(String src, InputType type) {
707721
ParserTokenizer tokenizer = new ParserTokenizer(src);
708722
NodeFactory factory = new NodeFactoryImp();
709-
ParserErrorCallback errorCb = new ParserErrorCallback() {
710-
@Override
711-
public void onError(ParserErrorCallback.ErrorType type, int start, int end, String message) {
712-
System.err.println(String.format("TODO: %s[%d:%d]: %s", type.name(), start, end, message));
713-
}
714-
};
715723
FExprParser fexpParser = new FExprParser() {
716724
@Override
717725
public ExprTy parse(String code) {
718726
ParserTokenizer tok = new ParserTokenizer(code);
719-
return new Parser(tok, factory, this, errorCb).fstring_rule();
727+
return new Parser(tok, factory, this).fstring_rule();
720728
}
721729
};
722-
Parser parser = new Parser(tokenizer, factory, fexpParser, errorCb);
723-
ModTy result = parser.file_rule();
730+
Parser parser = new Parser(tokenizer, factory, fexpParser);
731+
ModTy result = (ModTy) parser.parse(type);
724732
Compiler compiler = new Compiler();
725733
CompilationUnit cu = compiler.compile(result, EnumSet.noneOf(Compiler.Flags.class), 2);
726734
CodeUnit co = cu.assemble(0);
@@ -741,7 +749,7 @@ private void checkCodeUnit(CodeUnit co) {
741749
Assert.assertEquals(Files.readString(goldenFile), coString);
742750
}
743751
} catch (IOException ex) {
744-
Assert.assertTrue(ex.getMessage(), false);
752+
Assert.fail(ex.getMessage());
745753
}
746754
}
747755

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Disassembly of <module>:
2+
000000 0 LOAD_BYTE 1
3+
000000 2 RETURN_VALUE
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Disassembly of <module>:
2+
000000 0 LOAD_BYTE 1
3+
000000 2 PRINT_EXPR
4+
000000 3 LOAD_NONE
5+
000000 4 RETURN_VALUE

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@
207207
import com.oracle.graal.python.nodes.util.CastToJavaIntExactNode;
208208
import com.oracle.graal.python.nodes.util.CastToJavaLongExactNode;
209209
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
210+
import com.oracle.graal.python.pegparser.InputType;
210211
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
211212
import com.oracle.graal.python.runtime.PythonContext;
212213
import com.oracle.graal.python.runtime.PythonOptions;
@@ -1041,12 +1042,15 @@ PCode compile(String expression, String filename, String mode, int kwFlags, Obje
10411042
Supplier<CallTarget> createCode = () -> {
10421043
if (pm == ParserMode.File) {
10431044
Source source = PythonLanguage.newSource(context, finalCode, filename, mayBeFromFile, PythonLanguage.getCompileMimeType(kwOptimize));
1044-
return getContext().getEnv().parsePublic(source);
1045+
return context.getEnv().parsePublic(source);
10451046
} else if (pm == ParserMode.Eval) {
10461047
Source source = PythonLanguage.newSource(context, finalCode, filename, mayBeFromFile, PythonLanguage.getEvalMimeType(kwOptimize));
1047-
return getContext().getEnv().parsePublic(source);
1048+
return context.getEnv().parsePublic(source);
10481049
} else {
10491050
Source source = PythonLanguage.newSource(context, finalCode, filename, mayBeFromFile, PythonLanguage.MIME_TYPE);
1051+
if (context.getOption(PythonOptions.EnableBytecodeInterpreter)) {
1052+
return context.getLanguage().parseForBytecodeInterpreter(context, source, InputType.SINGLE, false, kwOptimize);
1053+
}
10501054
return PythonUtils.getOrCreateCallTarget((RootNode) getCore().getParser().parse(pm, kwOptimize, getCore(), source, null, null));
10511055
}
10521056
};

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/Compiler.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
import static com.oracle.graal.python.compiler.OpCodes.POP_AND_JUMP_IF_TRUE;
105105
import static com.oracle.graal.python.compiler.OpCodes.POP_EXCEPT;
106106
import static com.oracle.graal.python.compiler.OpCodes.POP_TOP;
107+
import static com.oracle.graal.python.compiler.OpCodes.PRINT_EXPR;
107108
import static com.oracle.graal.python.compiler.OpCodes.PUSH_EXC_INFO;
108109
import static com.oracle.graal.python.compiler.OpCodes.RAISE_VARARGS;
109110
import static com.oracle.graal.python.compiler.OpCodes.RESUME_YIELD;
@@ -1674,7 +1675,10 @@ public Void visit(StmtTy.Delete node) {
16741675
@Override
16751676
public Void visit(StmtTy.Expr node) {
16761677
setLocation(node);
1677-
if (!(node.value instanceof ExprTy.Constant)) {
1678+
if (interactive) {
1679+
node.value.accept(this);
1680+
addOp(PRINT_EXPR);
1681+
} else if (!(node.value instanceof ExprTy.Constant)) {
16781682
node.value.accept(this);
16791683
addOp(POP_TOP);
16801684
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/OpCodes.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@ public enum OpCodes {
304304
* Pops: level (must be {@code int})
305305
*/
306306
IMPORT_STAR(1, 1, 0),
307+
/**
308+
* Prints the top of the stack. Used by "single" parsing mode to echo expressions.
309+
*
310+
* Pops: the value to print
311+
*/
312+
PRINT_EXPR(0, 1, 0),
307313

308314
// load bytecodes for special constants
309315
LOAD_NONE(0, 0, 1),

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,11 @@ public final class PBytecodeRootNode extends PRootNode implements BytecodeOSRNod
250250
private static final NodeSupplier<BuiltinFunctions.FormatNode> NODE_FORMAT = BuiltinFunctions.FormatNode::create;
251251
private static final NodeSupplier<SendNode> NODE_SEND = SendNode::create;
252252
private static final NodeSupplier<ThrowNode> NODE_THROW = ThrowNode::create;
253-
254253
private static final WriteGlobalNode UNCACHED_WRITE_GLOBAL = WriteGlobalNode.getUncached();
255254
private static final NodeFunction<String, WriteGlobalNode> NODE_WRITE_GLOBAL = WriteGlobalNode::create;
256-
257255
private static final NodeFunction<String, DeleteGlobalNode> NODE_DELETE_GLOBAL = DeleteGlobalNode::create;
256+
private static final PrintExprNode UNCACHED_PRINT_EXPR = PrintExprNode.getUncached();
257+
private static final NodeSupplier<PrintExprNode> NODE_PRINT_EXPR = PrintExprNode::create;
258258

259259
private static final IntNodeFunction<UnaryOpNode> UNARY_OP_FACTORY = (int op) -> {
260260
switch (op) {
@@ -1432,6 +1432,12 @@ Object executeFromBci(VirtualFrame virtualFrame, int initialBci, int initialStac
14321432
continue;
14331433
}
14341434
}
1435+
case OpCodesConstants.PRINT_EXPR: {
1436+
PrintExprNode printExprNode = insertChildNode(localNodes, beginBci, UNCACHED_PRINT_EXPR, NODE_PRINT_EXPR);
1437+
printExprNode.execute(virtualFrame, localFrame.getObject(stackTop));
1438+
localFrame.setObject(stackTop--, null);
1439+
break;
1440+
}
14351441
case OpCodesConstants.EXTENDED_ARG: {
14361442
oparg |= Byte.toUnsignedInt(localBC[++bci]);
14371443
oparg <<= 8;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (c) 2022, 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.bytecode;
42+
43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RuntimeError;
44+
45+
import com.oracle.graal.python.builtins.objects.PNone;
46+
import com.oracle.graal.python.builtins.objects.module.PythonModule;
47+
import com.oracle.graal.python.lib.PyObjectLookupAttr;
48+
import com.oracle.graal.python.nodes.BuiltinNames;
49+
import com.oracle.graal.python.nodes.ErrorMessages;
50+
import com.oracle.graal.python.nodes.PNodeWithContext;
51+
import com.oracle.graal.python.nodes.PRaiseNode;
52+
import com.oracle.graal.python.nodes.call.CallNode;
53+
import com.oracle.truffle.api.CompilerDirectives;
54+
import com.oracle.truffle.api.dsl.Cached;
55+
import com.oracle.truffle.api.dsl.GenerateUncached;
56+
import com.oracle.truffle.api.dsl.Specialization;
57+
import com.oracle.truffle.api.frame.Frame;
58+
import com.oracle.truffle.api.frame.VirtualFrame;
59+
60+
@GenerateUncached
61+
public abstract class PrintExprNode extends PNodeWithContext {
62+
public abstract void execute(Frame frame, Object object);
63+
64+
@Specialization
65+
void print(VirtualFrame frame, Object object,
66+
@Cached PyObjectLookupAttr lookupAttr,
67+
@Cached CallNode callNode) {
68+
PythonModule sysModule = getContext().lookupBuiltinModule("sys");
69+
Object displayhook = lookupAttr.execute(frame, sysModule, BuiltinNames.DISPLAYHOOK);
70+
if (displayhook == PNone.NO_VALUE) {
71+
CompilerDirectives.transferToInterpreterAndInvalidate();
72+
throw PRaiseNode.raiseUncached(this, RuntimeError, ErrorMessages.LOST_SYSDISPLAYHOOK);
73+
}
74+
callNode.execute(frame, displayhook, object);
75+
}
76+
77+
public static PrintExprNode create() {
78+
return PrintExprNodeGen.create();
79+
}
80+
81+
public static PrintExprNode getUncached() {
82+
return PrintExprNodeGen.getUncached();
83+
}
84+
}

0 commit comments

Comments
 (0)