4040 */
4141package com .oracle .graal .python .nodes .argument ;
4242
43+ import java .util .ArrayList ;
44+
4345import com .oracle .graal .python .builtins .objects .function .Arity ;
4446import com .oracle .graal .python .builtins .objects .function .PArguments ;
4547import com .oracle .graal .python .builtins .objects .function .PKeyword ;
48+ import com .oracle .graal .python .nodes .PBaseNode ;
4649import com .oracle .graal .python .nodes .argument .ApplyKeywordsNodeGen .SearchNamedParameterNodeGen ;
50+ import com .oracle .graal .python .runtime .exception .PythonErrorType ;
4751import com .oracle .truffle .api .dsl .Cached ;
4852import com .oracle .truffle .api .dsl .Specialization ;
4953import com .oracle .truffle .api .nodes .ExplodeLoop ;
5054import com .oracle .truffle .api .nodes .Node ;
5155
52- public abstract class ApplyKeywordsNode extends Node {
56+ public abstract class ApplyKeywordsNode extends PBaseNode {
5357 public abstract Object [] execute (Arity calleeArity , Object [] arguments , PKeyword [] keywords );
5458
5559 public static ApplyKeywordsNode create () {
5660 return ApplyKeywordsNodeGen .create ();
5761 }
5862
59- private static Object [] applyKeywordArgs (Arity calleeArity , Object [] arguments , PKeyword [] keywords ) {
60- String [] parameters = calleeArity .getParameterIds ();
61- Object [] combined = arguments ;
62- if (parameters .length > PArguments .getUserArgumentLength (arguments )) {
63- combined = PArguments .create (parameters .length );
64- System .arraycopy (arguments , 0 , combined , 0 , arguments .length );
65- }
66- PKeyword [] unusedKeywords = new PKeyword [keywords .length ];
67- int unusedKeywordsIdx = 0 ;
68- for (int i = 0 ; i < keywords .length ; i ++) {
69- PKeyword keyarg = keywords [i ];
70- int keywordIdx = -1 ;
71- for (int j = 0 ; j < parameters .length ; j ++) {
72- if (parameters [j ].equals (keyarg .getName ())) {
73- keywordIdx = j ;
74- break ;
75- }
76- }
77-
78- if (keywordIdx != -1 ) {
79- assert PArguments .getArgument (combined , keywordIdx ) == null : calleeArity .getFunctionName () + " got multiple values for argument '" + keyarg .getName () + "'" ;
80- PArguments .setArgument (combined , keywordIdx , keyarg .getValue ());
81- } else {
82- unusedKeywords [unusedKeywordsIdx ] = keyarg ;
83- unusedKeywordsIdx ++;
84- }
85- }
86- PKeyword [] keywordArguments = new PKeyword [unusedKeywordsIdx ];
87- System .arraycopy (unusedKeywords , 0 , keywordArguments , 0 , unusedKeywordsIdx );
88- PArguments .setKeywordArguments (combined , keywordArguments );
89- return combined ;
90- }
91-
9263 int getUserArgumentLength (Object [] arguments ) {
9364 return PArguments .getUserArgumentLength (arguments );
9465 }
@@ -97,6 +68,13 @@ SearchNamedParameterNode createSearchNamedParameterNode() {
9768 return SearchNamedParameterNodeGen .create ();
9869 }
9970
71+ @ ExplodeLoop
72+ private static void copyArgs (Object [] src , Object [] dst , int len ) {
73+ for (int i = 0 ; i < len ; i ++) {
74+ dst [i ] = src [i ];
75+ }
76+ }
77+
10078 @ Specialization (guards = {"kwLen == keywords.length" , "argLen == arguments.length" , "calleeArity == cachedArity" })
10179 @ ExplodeLoop
10280 Object [] applyCached (Arity calleeArity , Object [] arguments , PKeyword [] keywords ,
@@ -110,32 +88,58 @@ Object[] applyCached(Arity calleeArity, Object[] arguments, PKeyword[] keywords,
11088 Object [] combined = arguments ;
11189 if (paramLen > userArgLen ) {
11290 combined = PArguments .create (paramLen );
113- for (int i = 0 ; i < argLen ; i ++) {
114- combined [i ] = arguments [i ];
115- }
91+ copyArgs (arguments , combined , argLen );
11692 }
117- PKeyword [] unusedKeywords = new PKeyword [ kwLen ];
118- int unusedKeywordsIdx = 0 ;
93+
94+ ArrayList < PKeyword > unusedKeywords = new ArrayList <>() ;
11995 for (int i = 0 ; i < kwLen ; i ++) {
120- PKeyword keyarg = keywords [i ];
121- int keywordIdx = searchParamNode .execute (parameters , keyarg .getName ());
122- if (keywordIdx != -1 ) {
123- assert PArguments .getArgument (combined , keywordIdx ) == null : calleeArity .getFunctionName () + " got multiple values for argument '" + keyarg .getName () + "'" ;
124- PArguments .setArgument (combined , keywordIdx , keyarg .getValue ());
96+ PKeyword kwArg = keywords [i ];
97+ int kwIdx = searchParamNode .execute (parameters , kwArg .getName ());
98+
99+ if (kwIdx != -1 ) {
100+ if (PArguments .getArgument (combined , kwIdx ) != null ) {
101+ throw raise (PythonErrorType .TypeError , "%s() got multiple values for argument '%s'" , calleeArity .getFunctionName (), kwArg .getName ());
102+ }
103+ PArguments .setArgument (combined , kwIdx , kwArg .getValue ());
125104 } else {
126- unusedKeywords [unusedKeywordsIdx ] = keyarg ;
127- unusedKeywordsIdx ++;
105+ unusedKeywords .add (kwArg );
128106 }
129107 }
130- PKeyword [] keywordArguments = new PKeyword [unusedKeywordsIdx ];
131- System .arraycopy (unusedKeywords , 0 , keywordArguments , 0 , unusedKeywordsIdx );
132- PArguments .setKeywordArguments (combined , keywordArguments );
108+ PArguments .setKeywordArguments (combined , unusedKeywords .toArray (new PKeyword [unusedKeywords .size ()]));
133109 return combined ;
134110 }
135111
136112 @ Specialization (replaces = "applyCached" )
137113 Object [] applyUncached (Arity calleeArity , Object [] arguments , PKeyword [] keywords ) {
138- return applyKeywordArgs (calleeArity , arguments , keywords );
114+ String [] parameters = calleeArity .getParameterIds ();
115+ Object [] combined = arguments ;
116+ if (parameters .length > PArguments .getUserArgumentLength (arguments )) {
117+ combined = PArguments .create (parameters .length );
118+ System .arraycopy (arguments , 0 , combined , 0 , arguments .length );
119+ }
120+
121+ ArrayList <PKeyword > unusedKeywords = new ArrayList <>();
122+ for (int i = 0 ; i < keywords .length ; i ++) {
123+ PKeyword kwArg = keywords [i ];
124+ int kwIdx = -1 ;
125+ for (int j = 0 ; j < parameters .length ; j ++) {
126+ if (parameters [j ].equals (kwArg .getName ())) {
127+ kwIdx = j ;
128+ break ;
129+ }
130+ }
131+
132+ if (kwIdx != -1 ) {
133+ if (PArguments .getArgument (combined , kwIdx ) != null ) {
134+ throw raise (PythonErrorType .TypeError , "%s() got multiple values for argument '%s'" , calleeArity .getFunctionName (), kwArg .getName ());
135+ }
136+ PArguments .setArgument (combined , kwIdx , kwArg .getValue ());
137+ } else {
138+ unusedKeywords .add (kwArg );
139+ }
140+ }
141+ PArguments .setKeywordArguments (combined , unusedKeywords .toArray (new PKeyword [unusedKeywords .size ()]));
142+ return combined ;
139143 }
140144
141145 protected abstract static class SearchNamedParameterNode extends Node {
0 commit comments