43
43
import com .oracle .graal .python .PythonLanguage ;
44
44
import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
45
45
import com .oracle .graal .python .builtins .objects .PNone ;
46
- import com .oracle .graal .python .builtins .objects .cell .PCell ;
47
46
import com .oracle .graal .python .builtins .objects .common .HashingStorageNodes ;
48
47
import com .oracle .graal .python .builtins .objects .dict .PDict ;
49
48
import com .oracle .graal .python .builtins .objects .function .PArguments ;
70
69
import com .oracle .truffle .api .RootCallTarget ;
71
70
import com .oracle .truffle .api .Truffle ;
72
71
import com .oracle .truffle .api .TruffleLanguage .ContextReference ;
73
- import com .oracle .truffle .api .frame .FrameDescriptor ;
74
- import com .oracle .truffle .api .frame .FrameSlot ;
75
- import com .oracle .truffle .api .frame .FrameSlotKind ;
76
- import com .oracle .truffle .api .frame .MaterializedFrame ;
77
72
import com .oracle .truffle .api .frame .VirtualFrame ;
78
73
import com .oracle .truffle .api .nodes .RootNode ;
79
74
import com .oracle .truffle .api .source .Source ;
@@ -115,13 +110,12 @@ public PCode execute(VirtualFrame frame, LazyPythonClass cls, int argcount, int
115
110
}
116
111
117
112
@ TruffleBoundary
118
- private PCode createCode (LazyPythonClass cls , int argcount , int kwonlyargcount ,
113
+ private static PCode createCode (LazyPythonClass cls , int argcount , int kwonlyargcount ,
119
114
int nlocals , int stacksize , int flags ,
120
115
byte [] codestring , Object [] constants , Object [] names ,
121
116
Object [] varnames , Object [] freevars , Object [] cellvars ,
122
117
String filename , String name , int firstlineno ,
123
118
byte [] lnotab ) {
124
-
125
119
PythonObjectFactory factory = PythonObjectFactory .getUncached ();
126
120
RootCallTarget callTarget = null ;
127
121
@@ -130,22 +124,11 @@ private PCode createCode(LazyPythonClass cls, int argcount, int kwonlyargcount,
130
124
if (codestring .length > 0 ) {
131
125
PythonCore core = PythonLanguage .getCore ();
132
126
if ((flags & PCode .FLAG_MODULE ) == 0 ) {
133
- // we're looking for the function, not the module
134
- String funcdef = createFuncdef (codestring , freevars , name );
135
- MaterializedFrame frame = getFrameForFreeVars (freevars , argcount );
136
- rootNode = (RootNode ) core .getParser ().parse (ParserMode .File , core , Source .newBuilder (PythonLanguage .ID , funcdef , name ).build (), frame );
137
- Object [] args = PArguments .create ();
138
- PDict globals = factory .createDict ();
139
- PArguments .setGlobals (args , globals );
140
- Object function = InvokeNode .invokeUncached (Truffle .getRuntime ().createCallTarget (rootNode ), args );
141
- if (function instanceof PFunction ) {
142
- rootNode = ((PFunction ) function ).getFunctionRootNode ();
143
- } else {
144
- throw PRaiseNode .getUncached ().raise (PythonBuiltinClassType .ValueError , "got an invalid codestring trying to create a function code object" );
145
- }
127
+ String funcdef = createFuncdef (argcount , kwonlyargcount , flags , codestring , varnames , freevars , name );
128
+ rootNode = getFunctionFromCode (core , factory , name , funcdef ).getFunctionRootNode ();
129
+ rootNode = patchConstantsAndGlobalNames (rootNode , constants , names );
146
130
} else {
147
- MaterializedFrame frame = getFrameForFreeVars (freevars , argcount );
148
- rootNode = (RootNode ) core .getParser ().parse (ParserMode .File , core , Source .newBuilder (PythonLanguage .ID , new String (codestring ), name ).build (), frame );
131
+ rootNode = (RootNode ) core .getParser ().parse (ParserMode .File , core , Source .newBuilder (PythonLanguage .ID , new String (codestring ), name ).build (), null );
149
132
assert rootNode instanceof ModuleRootNode ;
150
133
}
151
134
callTarget = Truffle .getRuntime ().createCallTarget (rootNode );
@@ -173,43 +156,95 @@ public boolean isPythonInternal() {
173
156
return factory .createCode (cls , callTarget , signature , nlocals , stacksize , flags , codestring , constants , names , varnames , freevars , cellvars , filename , name , firstlineno , lnotab );
174
157
}
175
158
176
- private MaterializedFrame getFrameForFreeVars (Object [] freevars , int argcount ) {
177
- MaterializedFrame frame = null ;
178
- if (freevars .length > 0 ) {
179
- FrameDescriptor frameDescriptor = new FrameDescriptor ();
180
- frame = Truffle .getRuntime ().createMaterializedFrame (PArguments .create (argcount ), frameDescriptor );
181
- for (int i = 0 ; i < freevars .length ; i ++) {
182
- Object ident = freevars [i ];
183
- FrameSlot slot = frameDescriptor .addFrameSlot (ident );
184
- frameDescriptor .setFrameSlotKind (slot , FrameSlotKind .Object );
185
- frame .setObject (slot , new PCell (Truffle .getRuntime ().createAssumption ("cell is effectively final" )));
186
- }
159
+ private static RootNode patchConstantsAndGlobalNames (RootNode rootNode , Object [] constants , Object [] names ) {
160
+ // TODO: fill in updated constants, names, filename, and firstlineno
161
+ for (int i = 0 ; i < constants .length ; i ++) {
162
+ // TODO: replace constants if they changed with the new ones
163
+ }
164
+ for (int i = 0 ; i < names .length ; i ++) {
165
+ // TODO: replace global names if they changed
187
166
}
188
- return frame ;
167
+ return rootNode ;
189
168
}
190
169
191
- private static String createFuncdef (byte [] codestring , Object [] freevars , String name ) {
192
- CompilerAsserts .neverPartOfCompilation ();
193
- String codeStr = new String (codestring );
194
- boolean isLambda = codeStr .trim ().startsWith ("lambda" );
195
- // we build an outer function to provide the initial scoping
196
- String outernme = "_____" + System .nanoTime ();
197
- StringBuilder sb = new StringBuilder ();
198
- sb .append ("def " ).append (outernme ).append ("():\n " );
199
- for (Object f : freevars ) {
200
- String freevar = CastToJavaStringNode .getUncached ().execute (f );
201
- if (freevar != null ) {
202
- sb .append (" " ).append (freevar ).append (" = None\n " );
170
+ private static PFunction getFunctionFromCode (PythonCore core , PythonObjectFactory factory , String name , String funcdef ) {
171
+ RootNode rootNode = (RootNode ) core .getParser ().parse (ParserMode .File , core , Source .newBuilder (PythonLanguage .ID , funcdef , name ).build (), null );
172
+ Object [] args = PArguments .create ();
173
+ PDict globals = factory .createDict ();
174
+ PArguments .setGlobals (args , globals );
175
+ Object returnValue = InvokeNode .invokeUncached (Truffle .getRuntime ().createCallTarget (rootNode ), args );
176
+ if (!(returnValue instanceof PFunction )) {
177
+ throw PRaiseNode .getUncached ().raise (PythonBuiltinClassType .ValueError , "got an invalid codestring trying to create a function code object" );
178
+ }
179
+ return (PFunction ) returnValue ;
180
+ }
181
+
182
+ private static String createFuncdef (int argcount , int kwonlyargcount , int flags , byte [] codestring , Object [] varnames , Object [] freevars , String name ) {
183
+ String indent = " " ;
184
+ StringBuilder funcdef = new StringBuilder ();
185
+ long outerName = System .nanoTime ();
186
+ funcdef .append ("def outer" ).append (outerName ).append ("():\n " );
187
+ for (Object freevar : freevars ) {
188
+ funcdef .append (indent ).append (CastToJavaStringNode .getUncached ().execute (freevar )).append (" = None\n " );
189
+ }
190
+
191
+ boolean isLambda = (flags & PCode .FLAG_LAMBDA ) != 0 ;
192
+ if (isLambda ) {
193
+ funcdef .append (indent ).append ("return lambda " );
194
+ } else {
195
+ funcdef .append (indent ).append ("def " ).append (name ).append ("(" );
196
+ }
197
+ int varnameIdx = 0 ;
198
+ for (; varnameIdx < argcount ; varnameIdx ++) {
199
+ funcdef .append (CastToJavaStringNode .getUncached ().execute (varnames [varnameIdx ])).append ("," );
200
+ }
201
+ if ((flags & PCode .FLAG_VAR_ARGS ) != 0 ) {
202
+ // vararg name is after kwargs names
203
+ funcdef .append ("*" ).append (CastToJavaStringNode .getUncached ().execute (varnames [varnameIdx + kwonlyargcount ])).append ("," );
204
+ }
205
+ for (; varnameIdx < kwonlyargcount ; varnameIdx ++) {
206
+ funcdef .append (CastToJavaStringNode .getUncached ().execute (varnames [varnameIdx ])).append ("=None," );
207
+ }
208
+ if ((flags & PCode .FLAG_VAR_KW_ARGS ) != 0 ) {
209
+ if ((flags & PCode .FLAG_VAR_ARGS ) != 0 ) {
210
+ varnameIdx ++;
203
211
}
212
+ funcdef .append ("**" ).append (CastToJavaStringNode .getUncached ().execute (varnames [varnameIdx ])).append ("," );
204
213
}
214
+
205
215
if (isLambda ) {
206
- sb .append (" " ).append ("return " ) .append (codeStr );
216
+ funcdef .append (": " ).append (new String ( codestring )) .append (" \n " );
207
217
} else {
208
- sb .append (" " ).append (codeStr ).append ("\n " );
209
- sb .append (" " ).append ("return " ).append (name );
218
+ funcdef .append ("):\n " );
219
+
220
+ String [] lines = new String (codestring ).split ("\n " );
221
+ String functionIndent = " " ;
222
+ String firstLineIndent = "" ;
223
+
224
+ // find indent inside the function to correctly insert nonlocal declarations
225
+ for (String line : lines ) {
226
+ if (!line .trim ().isEmpty ()) {
227
+ StringBuilder sb = new StringBuilder ();
228
+ int i = 0 ;
229
+ char ch ;
230
+ while (Character .isWhitespace (ch = line .charAt (i ++))) {
231
+ sb .append (ch );
232
+ }
233
+ firstLineIndent = sb .toString ();
234
+ break ;
235
+ }
236
+ }
237
+ for (Object freevar : freevars ) {
238
+ funcdef .append (indent ).append (functionIndent ).append (firstLineIndent ).append ("nonlocal " ).append (CastToJavaStringNode .getUncached ().execute (freevar )).append ("\n " );
239
+ }
240
+ for (String line : lines ) {
241
+ funcdef .append (indent ).append (functionIndent ).append (line ).append ("\n " );
242
+ }
243
+ funcdef .append (indent ).append ("return " ).append (name ).append ("\n " );
210
244
}
211
- sb .append ("\n \n " ).append (outernme ).append ("()" );
212
- return sb .toString ();
245
+
246
+ funcdef .append ("outer" ).append (outerName ).append ("()" );
247
+ return funcdef .toString ();
213
248
}
214
249
215
250
private static Signature createSignature (int flags , int argcount , int kwonlyargcount , Object [] varnames ) {
@@ -240,14 +275,6 @@ private static Signature createSignature(int flags, int argcount, int kwonlyargc
240
275
return new Signature (PCode .takesVarKeywordArgs (flags ), PCode .takesVarArgs (flags ) ? argcount : -1 , !PCode .takesVarArgs (flags ) && kwonlyargcount > 0 , paramNames , kwNames );
241
276
}
242
277
243
- private HashingStorageNodes .GetItemNode ensureGetItemNode () {
244
- if (getItemNode == null ) {
245
- CompilerDirectives .transferToInterpreterAndInvalidate ();
246
- getItemNode = insert (HashingStorageNodes .GetItemNode .create ());
247
- }
248
- return getItemNode ;
249
- }
250
-
251
278
private ContextReference <PythonContext > getContextRef () {
252
279
if (contextRef == null ) {
253
280
CompilerDirectives .transferToInterpreterAndInvalidate ();
0 commit comments