40
40
*/
41
41
package com .oracle .graal .python .builtins .objects .code ;
42
42
43
- import java .util .ArrayList ;
44
43
import java .util .Arrays ;
45
44
import java .util .HashSet ;
46
45
import java .util .List ;
47
46
import java .util .Set ;
47
+ import java .util .stream .Collectors ;
48
48
49
49
import com .oracle .graal .python .builtins .objects .object .PythonBuiltinObject ;
50
50
import com .oracle .graal .python .builtins .objects .type .PythonClass ;
51
51
import com .oracle .graal .python .nodes .ModuleRootNode ;
52
52
import com .oracle .graal .python .nodes .argument .ReadIndexedArgumentNode ;
53
53
import com .oracle .graal .python .nodes .argument .ReadKeywordNode ;
54
+ import com .oracle .graal .python .nodes .frame .WriteIdentifierNode ;
54
55
import com .oracle .graal .python .nodes .function .FunctionRootNode ;
55
56
import com .oracle .graal .python .nodes .generator .GeneratorFunctionRootNode ;
56
57
import com .oracle .graal .python .runtime .PythonCore ;
57
58
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
59
+ import com .oracle .truffle .api .nodes .Node ;
58
60
import com .oracle .truffle .api .nodes .NodeUtil ;
59
61
import com .oracle .truffle .api .nodes .RootNode ;
60
62
import com .oracle .truffle .api .source .SourceSection ;
61
63
62
64
public class PCode extends PythonBuiltinObject {
63
- private final RootNode result ;
65
+ private final RootNode rootNode ;
66
+ // number of arguments (not including keyword only arguments, * or ** args)
64
67
private final int argcount ;
68
+ // number of keyword only arguments (not including ** arg)
65
69
private final int kwonlyargcount ;
70
+ // number of local variables
66
71
private final int nlocals ;
72
+ // virtual machine stack space required
67
73
private final int stacksize ;
74
+ // bitmap of CO_* flags, read more
75
+ // (https://docs.python.org/3/library/inspect.html#inspect-module-co-flags)
68
76
private final int flags ;
77
+ // string of raw compiled bytecode
69
78
private final String codestring ;
79
+ // tuple of constants used in the bytecode
70
80
private final Object constants ;
81
+ // tuple of names of local variables
71
82
private final Object names ;
83
+ // tuple of names of arguments and local variables
72
84
private final Object [] varnames ;
85
+ // name of file in which this code object was created
73
86
private final String filename ;
87
+ // name with which this code object was defined
74
88
private final String name ;
89
+ // number of first line in Python source code
75
90
private final int firstlineno ;
91
+ // encoded mapping of line numbers to bytecode indices
76
92
private final Object lnotab ;
93
+ // tuple of names of free variables (referenced via a function’s closure)
77
94
private final Object [] freevars ;
95
+ // tuple of names of cell variables (referenced by containing scopes)
78
96
private final Object [] cellvars ;
79
97
80
98
@ TruffleBoundary
81
- public PCode (PythonClass cls , RootNode result , PythonCore core ) {
99
+ public PCode (PythonClass cls , RootNode rootNode , PythonCore core ) {
82
100
super (cls );
83
- this .result = result ;
101
+ this .rootNode = rootNode ;
84
102
// file stats
85
- this .filename = getFileName (this .result );
86
- this .name = getName (this .result );
87
- this .firstlineno = getFirstLineno (this .result );
103
+ this .filename = getFileName (this .rootNode );
104
+ this .name = getName (this .rootNode );
105
+ this .firstlineno = getFirstLineno (this .rootNode );
88
106
// arg stats
89
- ArgStats argStats = getArgStats (this .result );
107
+ ArgStats argStats = getArgStats (this .rootNode , core );
90
108
this .argcount = argStats .argCnt ;
91
109
this .kwonlyargcount = argStats .kwOnlyArgCnt ;
92
- // var stats
93
- String [] freevars = getFreeVars (this .result );
94
- String [] cellvars = getCellVars (this .result );
95
- Set <String > freeVarsSet = asSet (freevars );
96
- Set <String > cellVarsSet = asSet (cellvars );
97
- ArrayList <String > varNames = getVarNames (this .result , freeVarsSet , cellVarsSet , core );
98
-
99
- this .freevars = freevars ;
100
- this .cellvars = cellvars ;
101
- this .varnames = varNames .toArray ();
102
- this .nlocals = this .varnames .length ;
110
+ this .freevars = argStats .freeVars ;
111
+ this .cellvars = argStats .cellVars ;
112
+ this .varnames = argStats .varNames ;
113
+ this .nlocals = argStats .nLocals ;
103
114
104
115
this .stacksize = -1 ;
105
116
this .flags = -1 ;
@@ -114,7 +125,7 @@ public PCode(PythonClass cls, int argcount, int kwonlyargcount, int nlocals, int
114
125
String filename , String name , int firstlineno , Object lnotab , Object [] freevars ,
115
126
Object [] cellvars ) {
116
127
super (cls );
117
- this .result = null ;
128
+ this .rootNode = null ;
118
129
this .argcount = argcount ;
119
130
this .kwonlyargcount = kwonlyargcount ;
120
131
this .nlocals = nlocals ;
@@ -169,11 +180,7 @@ private static String getFileName(RootNode rootNode) {
169
180
170
181
private static int getFirstLineno (RootNode rootNode ) {
171
182
SourceSection sourceSection = rootNode .getSourceSection ();
172
- if (sourceSection == null ) {
173
- return 1 ;
174
- } else {
175
- return sourceSection .getStartLine ();
176
- }
183
+ return (sourceSection != null ) ? sourceSection .getStartLine () : 1 ;
177
184
}
178
185
179
186
private static String getName (RootNode rootNode ) {
@@ -188,46 +195,82 @@ private static String getName(RootNode rootNode) {
188
195
return name ;
189
196
}
190
197
191
- private static ArrayList <String > getVarNames ( RootNode rootNode , Set < String > freeVarsSet , Set < String > cellVarsSet , PythonCore core ) {
192
- // tuple of names of arguments and local variables
193
- ArrayList < String > variableNames = new ArrayList <>();
194
- for ( Object identifier : rootNode . getFrameDescriptor (). getIdentifiers ()) {
195
- if (identifier instanceof String ) {
196
- String varName = (String ) identifier ;
197
- if (core . getParser (). isIdentifier ( core , varName ) && ! freeVarsSet . contains ( varName ) && ! cellVarsSet . contains ( varName ) ) {
198
- variableNames .add (varName );
198
+ private static Set <String > getArgumentNames ( List < ReadIndexedArgumentNode > readIndexedArgumentNodes ) {
199
+ Set < String > argNames = new HashSet <>();
200
+ for ( ReadIndexedArgumentNode node : readIndexedArgumentNodes ) {
201
+ Node parent = node . getParent ();
202
+ if (parent instanceof WriteIdentifierNode ) {
203
+ Object identifier = (( WriteIdentifierNode ) parent ). getIdentifier () ;
204
+ if (identifier instanceof String ) {
205
+ argNames .add (( String ) identifier );
199
206
}
200
207
}
201
208
}
202
- return variableNames ;
209
+ return argNames ;
203
210
}
204
211
205
212
private final static class ArgStats {
206
213
public final int argCnt ;
207
214
private final int kwOnlyArgCnt ;
215
+ private final Object [] varNames ;
216
+ private final Object [] freeVars ;
217
+ private final Object [] cellVars ;
218
+ private final int nLocals ;
208
219
209
- private ArgStats (int argCnt , int kwOnlyArgCnt ) {
220
+ private ArgStats (int argCnt , int kwOnlyArgCnt , Object [] varNames , Object [] freeVars , Object [] cellVars ) {
210
221
this .argCnt = argCnt ;
211
222
this .kwOnlyArgCnt = kwOnlyArgCnt ;
223
+ this .varNames = varNames ;
224
+ this .freeVars = freeVars ;
225
+ this .cellVars = cellVars ;
226
+ this .nLocals = varNames .length ;
212
227
}
213
228
}
214
229
215
- private static ArgStats getArgStats (RootNode rootNode ) {
216
- int argC = NodeUtil .findAllNodeInstances (rootNode , ReadIndexedArgumentNode .class ).size ();
230
+ private static ArgStats getArgStats (RootNode rootNode , PythonCore core ) {
231
+ String [] freeVars = getFreeVars (rootNode );
232
+ String [] cellVars = getCellVars (rootNode );
233
+ Set <String > freeVarsSet = asSet (freeVars );
234
+ Set <String > cellVarsSet = asSet (cellVars );
235
+
236
+ List <ReadKeywordNode > readKeywordNodes = NodeUtil .findAllNodeInstances (rootNode , ReadKeywordNode .class );
237
+ List <ReadIndexedArgumentNode > readIndexedArgumentNodes = NodeUtil .findAllNodeInstances (rootNode , ReadIndexedArgumentNode .class );
238
+
239
+ Set <String > kwNames = readKeywordNodes .stream ().map (ReadKeywordNode ::getName ).collect (Collectors .toSet ());
240
+ Set <String > argNames = getArgumentNames (readIndexedArgumentNodes );
241
+
242
+ Set <String > allArgNames = new HashSet <>();
243
+ allArgNames .addAll (kwNames );
244
+ allArgNames .addAll (argNames );
245
+
246
+ int argC = readIndexedArgumentNodes .size ();
217
247
int kwOnlyArgC = 0 ;
218
- List <ReadKeywordNode > kwNodes = NodeUtil .findAllNodeInstances (rootNode , ReadKeywordNode .class );
219
- for (ReadKeywordNode kwNode : kwNodes ) {
220
- if (kwNode .canBePositional ()) {
221
- argC ++;
222
- } else {
248
+
249
+ for (ReadKeywordNode kwNode : readKeywordNodes ) {
250
+ if (!kwNode .canBePositional ()) {
223
251
kwOnlyArgC ++;
224
252
}
225
253
}
226
- return new ArgStats (argC , kwOnlyArgC );
254
+
255
+ Set <String > varNames = new HashSet <>();
256
+ for (Object identifier : rootNode .getFrameDescriptor ().getIdentifiers ()) {
257
+ if (identifier instanceof String ) {
258
+ String varName = (String ) identifier ;
259
+
260
+ if (core .getParser ().isIdentifier (core , varName )) {
261
+ if (allArgNames .contains (varName )) {
262
+ varNames .add (varName );
263
+ } else if (!freeVarsSet .contains (varName ) && !cellVarsSet .contains (varName )) {
264
+ varNames .add (varName );
265
+ }
266
+ }
267
+ }
268
+ }
269
+ return new ArgStats (argC , kwOnlyArgC , varNames .toArray (), freeVars , cellVars );
227
270
}
228
271
229
272
public RootNode getRootNode () {
230
- return result ;
273
+ return rootNode ;
231
274
}
232
275
233
276
public Object [] getFreeVars () {
0 commit comments