27
27
28
28
import com .oracle .graal .python .builtins .objects .function .PKeyword ;
29
29
import com .oracle .graal .python .nodes .BuiltinNames ;
30
+ import com .oracle .graal .python .nodes .EmptyNode ;
30
31
import com .oracle .graal .python .nodes .PNode ;
31
32
import com .oracle .graal .python .nodes .argument .keywords .KeywordArgumentsNode ;
32
33
import com .oracle .graal .python .nodes .argument .positional .PositionalArgumentsNode ;
33
34
import com .oracle .graal .python .nodes .attributes .GetAttributeNode ;
34
35
import com .oracle .graal .python .nodes .call .PythonCallNodeGen .GetCallAttributeNodeGen ;
35
36
import com .oracle .graal .python .nodes .call .special .LookupAndCallBinaryNode ;
36
37
import com .oracle .graal .python .nodes .frame .ReadGlobalOrBuiltinNode ;
38
+ import com .oracle .graal .python .nodes .literal .StringLiteralNode ;
37
39
import com .oracle .graal .python .runtime .exception .PythonErrorType ;
38
40
import com .oracle .truffle .api .debug .DebuggerTags ;
39
41
import com .oracle .truffle .api .dsl .Cached ;
40
42
import com .oracle .truffle .api .dsl .Fallback ;
41
43
import com .oracle .truffle .api .dsl .NodeChild ;
42
- import com .oracle .truffle .api .dsl .NodeChildren ;
43
44
import com .oracle .truffle .api .dsl .Specialization ;
45
+ import com .oracle .truffle .api .frame .VirtualFrame ;
44
46
import com .oracle .truffle .api .instrumentation .StandardTags ;
45
47
import com .oracle .truffle .api .instrumentation .Tag ;
46
48
import com .oracle .truffle .api .interop .ArityException ;
53
55
import com .oracle .truffle .api .nodes .Node ;
54
56
import com .oracle .truffle .api .profiles .BranchProfile ;
55
57
56
- @ NodeChildren ({ @ NodeChild ("calleeNode" ), @ NodeChild ( value = "arguments" , type = PositionalArgumentsNode . class ), @ NodeChild ( value = "keywords" , type = KeywordArgumentsNode . class )} )
58
+ @ NodeChild ("calleeNode" )
57
59
public abstract class PythonCallNode extends PNode {
60
+
58
61
@ Child private CallNode callNode = CallNode .create ();
59
62
63
+ /*
64
+ * Either "argument" or "positionalArgument" needs to be non-null (but not both), and
65
+ * "keywordArguments" may be null.
66
+ */
67
+ @ Children private final PNode [] argumentNodes ;
68
+ @ Child private PositionalArgumentsNode positionalArguments ;
69
+ @ Child private KeywordArgumentsNode keywordArguments ;
70
+
60
71
protected final String calleeName ;
61
72
62
- PythonCallNode (String calleeName ) {
73
+ PythonCallNode (String calleeName , PNode [] argumentNodes , PositionalArgumentsNode positionalArguments , KeywordArgumentsNode keywordArguments ) {
63
74
this .calleeName = calleeName ;
75
+ this .argumentNodes = argumentNodes ;
76
+ this .positionalArguments = positionalArguments ;
77
+ this .keywordArguments = keywordArguments ;
64
78
}
65
79
66
- public static PythonCallNode create (PNode calleeNode , PNode [] argumentNodes , PNode [] keywords , PNode starargs , PNode kwargs ) {
80
+ public static PythonCallNode create (PNode calleeNode , PNode [] argumentNodes , PNode [] keywords , PNode starArgs , PNode kwArgs ) {
81
+ assert !(starArgs instanceof EmptyNode ) : "pass null instead" ;
82
+ assert !(kwArgs instanceof EmptyNode ) : "pass null instead" ;
83
+
67
84
String calleeName = "~unknown" ;
68
85
PNode getCallableNode = calleeNode ;
69
86
70
87
if (calleeNode instanceof ReadGlobalOrBuiltinNode ) {
71
88
calleeName = ((ReadGlobalOrBuiltinNode ) calleeNode ).getAttributeId ();
72
89
} else if (calleeNode instanceof GetAttributeNode ) {
73
- getCallableNode = GetCallAttributeNodeGen .create (((GetAttributeNode ) calleeNode ).getObject (), ((GetAttributeNode ) calleeNode ).getKey ());
90
+ PNode key = ((GetAttributeNode ) calleeNode ).getKey ();
91
+ getCallableNode = GetCallAttributeNodeGen .create (((StringLiteralNode ) key ).getValue (), ((GetAttributeNode ) calleeNode ).getObject ());
92
+ }
93
+ KeywordArgumentsNode keywordArgumentsNode = kwArgs == null && keywords .length == 0 ? null : KeywordArgumentsNode .create (keywords , kwArgs );
94
+ if (starArgs == null ) {
95
+ return PythonCallNodeGen .create (calleeName , argumentNodes , null , keywordArgumentsNode , getCallableNode );
96
+ } else {
97
+ return PythonCallNodeGen .create (calleeName , null , PositionalArgumentsNode .create (argumentNodes , starArgs ), keywordArgumentsNode , getCallableNode );
74
98
}
75
-
76
- return PythonCallNodeGen .create (calleeName , getCallableNode , PositionalArgumentsNode .create (argumentNodes , starargs ), KeywordArgumentsNode .create (keywords , kwargs ));
77
99
}
78
100
79
- @ NodeChildren ({ @ NodeChild ("object" ), @ NodeChild ( "key" )} )
101
+ @ NodeChild ("object" )
80
102
protected abstract static class GetCallAttributeNode extends PNode {
81
103
104
+ private final String key ;
105
+
106
+ protected GetCallAttributeNode (String key ) {
107
+ this .key = key ;
108
+ }
109
+
82
110
@ Specialization (guards = "isForeignObject(object)" )
83
- Object getForeignInvoke (TruffleObject object , String key ) {
111
+ Object getForeignInvoke (TruffleObject object ) {
84
112
return new ForeignInvoke (object , key );
85
113
}
86
114
87
115
@ Specialization (guards = "!isForeignObject(object)" )
88
- Object getCallAttribute (Object object , Object key ,
116
+ Object getCallAttribute (Object object ,
89
117
@ Cached ("create(__GETATTRIBUTE__)" ) LookupAndCallBinaryNode getAttributeNode ) {
90
118
return getAttributeNode .executeObject (object , key );
91
119
}
@@ -110,18 +138,28 @@ public boolean hasSideEffectAsAnExpression() {
110
138
return true ;
111
139
}
112
140
141
+ private Object [] evaluateArguments (VirtualFrame frame ) {
142
+ return argumentNodes != null ? PositionalArgumentsNode .evaluateArguments (frame , argumentNodes ) : positionalArguments .execute (frame );
143
+ }
144
+
145
+ private PKeyword [] evaluateKeywords (VirtualFrame frame ) {
146
+ return keywordArguments == null ? PKeyword .EMPTY_KEYWORDS : keywordArguments .execute (frame );
147
+ }
148
+
113
149
protected static Node createInvoke () {
114
150
return Message .createInvoke (0 ).createNode ();
115
151
}
116
152
117
153
@ Specialization
118
- Object call (ForeignInvoke callable , Object [] arguments , PKeyword [] keywords ,
154
+ Object call (VirtualFrame frame , ForeignInvoke callable ,
119
155
@ Cached ("create()" ) BranchProfile keywordsError ,
120
156
@ Cached ("create()" ) BranchProfile nameError ,
121
157
@ Cached ("create()" ) BranchProfile typeError ,
122
158
@ Cached ("create()" ) BranchProfile invokeError ,
123
159
@ Cached ("create(__GETATTRIBUTE__)" ) LookupAndCallBinaryNode getAttrNode ,
124
160
@ Cached ("createInvoke()" ) Node invokeNode ) {
161
+ Object [] arguments = evaluateArguments (frame );
162
+ PKeyword [] keywords = evaluateKeywords (frame );
125
163
if (keywords .length != 0 ) {
126
164
keywordsError .enter ();
127
165
throw raise (PythonErrorType .TypeError , "foreign invocation does not support keyword arguments" );
@@ -143,7 +181,9 @@ Object call(ForeignInvoke callable, Object[] arguments, PKeyword[] keywords,
143
181
}
144
182
145
183
@ Fallback
146
- Object call (Object callable , Object [] arguments , PKeyword [] keywords ) {
184
+ Object call (VirtualFrame frame , Object callable ) {
185
+ Object [] arguments = evaluateArguments (frame );
186
+ PKeyword [] keywords = evaluateKeywords (frame );
147
187
return callNode .execute (callable , arguments , keywords );
148
188
}
149
189
0 commit comments