34
34
import java .io .IOException ;
35
35
import java .util .Arrays ;
36
36
import java .util .EnumSet ;
37
+ import java .util .List ;
37
38
import java .util .concurrent .ConcurrentHashMap ;
38
39
import java .util .concurrent .Semaphore ;
39
40
import java .util .logging .Level ;
65
66
import com .oracle .graal .python .nodes .PRootNode ;
66
67
import com .oracle .graal .python .nodes .RootNodeFactory ;
67
68
import com .oracle .graal .python .nodes .bytecode .PBytecodeRootNode ;
69
+ import com .oracle .graal .python .nodes .call .CallNode ;
68
70
import com .oracle .graal .python .nodes .control .TopLevelExceptionHandler ;
69
71
import com .oracle .graal .python .nodes .expression .ExpressionNode ;
70
72
import com .oracle .graal .python .nodes .util .BadOPCodeNode ;
71
73
import com .oracle .graal .python .parser .PythonParserImpl ;
72
74
import com .oracle .graal .python .pegparser .InputType ;
75
+ import com .oracle .graal .python .pegparser .NodeFactory ;
76
+ import com .oracle .graal .python .pegparser .NodeFactoryImp ;
73
77
import com .oracle .graal .python .pegparser .Parser ;
78
+ import com .oracle .graal .python .pegparser .sst .ArgTy ;
79
+ import com .oracle .graal .python .pegparser .sst .ArgumentsTy ;
74
80
import com .oracle .graal .python .pegparser .sst .ModTy ;
81
+ import com .oracle .graal .python .pegparser .sst .StmtTy ;
82
+ import com .oracle .graal .python .pegparser .tokenizer .SourceRange ;
75
83
import com .oracle .graal .python .runtime .GilNode ;
76
84
import com .oracle .graal .python .runtime .PythonContext ;
77
85
import com .oracle .graal .python .runtime .PythonContext .PythonThreadState ;
115
123
import com .oracle .truffle .api .object .Shape ;
116
124
import com .oracle .truffle .api .source .Source ;
117
125
import com .oracle .truffle .api .source .Source .SourceBuilder ;
126
+ import com .oracle .truffle .api .source .SourceSection ;
118
127
import com .oracle .truffle .api .strings .TruffleString ;
119
128
120
129
@ TruffleLanguage .Registration (id = PythonLanguage .ID , //
@@ -445,10 +454,10 @@ protected CallTarget parse(ParsingRequest request) {
445
454
}
446
455
}
447
456
if (MIME_TYPE_SOURCE_FOR_BYTECODE .equals (source .getMimeType ())) {
448
- return parseForBytecodeInterpreter (context , source , InputType .FILE , true , 0 , false );
457
+ return parseForBytecodeInterpreter (context , source , InputType .FILE , true , 0 , false , null );
449
458
}
450
459
if (MIME_TYPE_SOURCE_FOR_BYTECODE_COMPILE .equals (source .getMimeType ())) {
451
- return parseForBytecodeInterpreter (context , source , InputType .FILE , false , 0 , false );
460
+ return parseForBytecodeInterpreter (context , source , InputType .FILE , false , 0 , false , null );
452
461
}
453
462
throw CompilerDirectives .shouldNotReachHere ("unknown mime type: " + source .getMimeType ());
454
463
}
@@ -457,11 +466,11 @@ private CallTarget parseForBytecodeInterpreter(ParsingRequest request) {
457
466
PythonContext context = PythonContext .get (null );
458
467
Source source = request .getSource ();
459
468
if (source .getMimeType () == null || MIME_TYPE .equals (source .getMimeType ())) {
460
- if (!request .getArgumentNames ().isEmpty ()) {
461
- throw new IllegalStateException ("Not supported yet " );
469
+ if (!request .getArgumentNames ().isEmpty () && source . isInteractive () ) {
470
+ throw new IllegalStateException ("parse with arguments not allowed for interactive sources " );
462
471
}
463
472
InputType inputType = source .isInteractive () ? InputType .SINGLE : InputType .FILE ;
464
- return parseForBytecodeInterpreter (context , source , inputType , true , 0 , source .isInteractive ());
473
+ return parseForBytecodeInterpreter (context , source , inputType , true , 0 , source .isInteractive (), request . getArgumentNames () );
465
474
}
466
475
if (!request .getArgumentNames ().isEmpty ()) {
467
476
throw new IllegalStateException ("parse with arguments is only allowed for " + MIME_TYPE + " mime type" );
@@ -493,46 +502,52 @@ private CallTarget parseForBytecodeInterpreter(ParsingRequest request) {
493
502
for (int optimize = 0 ; optimize < MIME_TYPE_EVAL .length ; optimize ++) {
494
503
if (MIME_TYPE_EVAL [optimize ].equals (source .getMimeType ())) {
495
504
assert !source .isInteractive ();
496
- return parseForBytecodeInterpreter (context , source , InputType .EVAL , false , optimize , false );
505
+ return parseForBytecodeInterpreter (context , source , InputType .EVAL , false , optimize , false , null );
497
506
}
498
507
}
499
508
for (int optimize = 0 ; optimize < MIME_TYPE_COMPILE .length ; optimize ++) {
500
509
if (MIME_TYPE_COMPILE [optimize ].equals (source .getMimeType ())) {
501
510
assert !source .isInteractive ();
502
- return parseForBytecodeInterpreter (context , source , InputType .FILE , false , optimize , false );
511
+ return parseForBytecodeInterpreter (context , source , InputType .FILE , false , optimize , false , null );
503
512
}
504
513
}
505
514
if (MIME_TYPE_SOURCE_FOR_BYTECODE .equals (source .getMimeType ())) {
506
- return parseForBytecodeInterpreter (context , source , InputType .FILE , true , 0 , false );
515
+ return parseForBytecodeInterpreter (context , source , InputType .FILE , true , 0 , false , null );
507
516
}
508
517
if (MIME_TYPE_SOURCE_FOR_BYTECODE_COMPILE .equals (source .getMimeType ())) {
509
- return parseForBytecodeInterpreter (context , source , InputType .FILE , false , 0 , false );
518
+ return parseForBytecodeInterpreter (context , source , InputType .FILE , false , 0 , false , null );
510
519
}
511
520
throw CompilerDirectives .shouldNotReachHere ("unknown mime type: " + source .getMimeType ());
512
521
}
513
522
514
- public RootCallTarget parseForBytecodeInterpreter (PythonContext context , Source source , InputType type , boolean topLevel , int optimize , boolean interactiveTerminal ) {
523
+ public RootCallTarget parseForBytecodeInterpreter (PythonContext context , Source source , InputType type , boolean topLevel , int optimize , boolean interactiveTerminal , List < String > argumentNames ) {
515
524
RaisePythonExceptionErrorCallback errorCb = new RaisePythonExceptionErrorCallback (source , PythonOptions .isPExceptionWithJavaStacktrace (this ));
516
525
try {
517
526
Parser parser = Compiler .createParser (source .getCharacters ().toString (), errorCb , type , interactiveTerminal );
518
527
Compiler compiler = new Compiler (errorCb );
519
528
ModTy mod = (ModTy ) parser .parse ();
520
529
assert mod != null ;
530
+ boolean hasArguments = argumentNames != null && !argumentNames .isEmpty ();
531
+ if (hasArguments ) {
532
+ mod = transformASTForExecutionWithArguments (argumentNames , mod );
533
+ }
521
534
CompilationUnit cu = compiler .compile (mod , EnumSet .noneOf (Compiler .Flags .class ), optimize );
522
535
CodeUnit co = cu .assemble ();
523
- PBytecodeRootNode bytecodeRootNode = new PBytecodeRootNode (this , co , source , errorCb );
536
+ RootNode rootNode = new PBytecodeRootNode (this , co , source , errorCb );
524
537
GilNode gil = GilNode .getUncached ();
525
- boolean wasAcquired = gil .acquire (context , bytecodeRootNode );
538
+ boolean wasAcquired = gil .acquire (context , rootNode );
526
539
if (topLevel ) {
527
540
try {
528
541
errorCb .triggerDeprecationWarnings ();
529
542
} finally {
530
543
gil .release (context , wasAcquired );
531
544
}
532
545
}
533
- RootNode rootNode = bytecodeRootNode ;
546
+ if (hasArguments ) {
547
+ rootNode = new RootNodeWithArguments (this , rootNode );
548
+ }
534
549
if (topLevel && context .isCoreInitialized ()) {
535
- rootNode = new TopLevelExceptionHandler (this , bytecodeRootNode , source );
550
+ rootNode = new TopLevelExceptionHandler (this , rootNode , source );
536
551
}
537
552
return PythonUtils .getOrCreateCallTarget (rootNode );
538
553
} catch (PException e ) {
@@ -543,6 +558,56 @@ public RootCallTarget parseForBytecodeInterpreter(PythonContext context, Source
543
558
}
544
559
}
545
560
561
+ private ModTy transformASTForExecutionWithArguments (List <String > argumentNames , ModTy mod ) {
562
+ NodeFactory nodeFactory = new NodeFactoryImp ();
563
+ ArgTy [] astArgArray = new ArgTy [argumentNames .size ()];
564
+ for (int i = 0 ; i < astArgArray .length ; i ++) {
565
+ astArgArray [i ] = nodeFactory .createArgument (argumentNames .get (i ), null , null , SourceRange .ARTIFICIAL_RANGE );
566
+ }
567
+ ArgumentsTy astArgs = nodeFactory .createArguments (null , null , astArgArray , null , null );
568
+ StmtTy [] body = ((ModTy .Module ) mod ).body ;
569
+ if (body != null && body .length > 0 ) {
570
+ body = Arrays .copyOf (body , body .length );
571
+ StmtTy lastStmt = body [body .length - 1 ];
572
+ if (lastStmt instanceof StmtTy .Expr ) {
573
+ body [body .length - 1 ] = nodeFactory .createReturn (((StmtTy .Expr ) lastStmt ).value , lastStmt .getSourceRange ());
574
+ }
575
+ }
576
+ String fnName = "execute" ;
577
+ StmtTy astFunction = nodeFactory .createFunctionDef (fnName , astArgs , body , null , null , SourceRange .ARTIFICIAL_RANGE );
578
+ /*
579
+ * We cannot use a return in a module, but we piggy-back on the fact that we return the last
580
+ * expression in a module (see Compiler)
581
+ */
582
+ StmtTy astGetFunction = nodeFactory .createExpression (nodeFactory .createVariable (fnName , SourceRange .ARTIFICIAL_RANGE ));
583
+ return nodeFactory .createModule (new StmtTy []{astFunction , astGetFunction }, SourceRange .ARTIFICIAL_RANGE );
584
+ }
585
+
586
+ private static class RootNodeWithArguments extends RootNode {
587
+ private final RootNode innerRootNode ;
588
+ @ Child private DirectCallNode callModuleNode ;
589
+ @ Child private CallNode callFunctionNode ;
590
+
591
+ public RootNodeWithArguments (PythonLanguage language , RootNode innerRootNode ) {
592
+ super (language );
593
+ this .innerRootNode = innerRootNode ;
594
+ callModuleNode = DirectCallNode .create (innerRootNode .getCallTarget ());
595
+ callFunctionNode = CallNode .create ();
596
+ }
597
+
598
+ @ Override
599
+ public Object execute (VirtualFrame frame ) {
600
+ Object function = callModuleNode .call (frame .getArguments ());
601
+ Object [] arguments = PythonUtils .arrayCopyOfRange (frame .getArguments (), PArguments .USER_ARGUMENTS_OFFSET , frame .getArguments ().length );
602
+ return callFunctionNode .execute (frame , function , arguments );
603
+ }
604
+
605
+ @ Override
606
+ public SourceSection getSourceSection () {
607
+ return innerRootNode .getSourceSection ();
608
+ }
609
+ }
610
+
546
611
private RootNode doParse (PythonContext context , Source source , int optimize ) {
547
612
ParserMode mode ;
548
613
if (source .isInteractive ()) {
@@ -991,5 +1056,4 @@ public RootCallTarget getDescriptorCallTarget(BuiltinMethodDescriptor descriptor
991
1056
assert callTarget != null : "Missing call target for builtin slot descriptor " + descriptor ;
992
1057
return callTarget ;
993
1058
}
994
-
995
1059
}
0 commit comments