Skip to content

Commit 3258c05

Browse files
committed
PartialBuiltins: fix __repr__ (mutate keywords)
1 parent 5066666 commit 3258c05

File tree

4 files changed

+163
-85
lines changed

4 files changed

+163
-85
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/FunctoolsModuleBuiltins.java

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*/
4141
package com.oracle.graal.python.builtins.modules;
4242

43+
import static com.oracle.graal.python.builtins.objects.partial.PartialBuiltins.getNewPartialArgs;
4344
import static com.oracle.graal.python.nodes.BuiltinNames.PARTIAL;
4445
import static com.oracle.graal.python.nodes.ErrorMessages.REDUCE_EMPTY_SEQ;
4546
import static com.oracle.graal.python.nodes.ErrorMessages.S_ARG_MUST_BE_CALLABLE;
@@ -53,6 +54,9 @@
5354
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5455
import com.oracle.graal.python.builtins.PythonBuiltins;
5556
import com.oracle.graal.python.builtins.objects.PNone;
57+
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
58+
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
59+
import com.oracle.graal.python.builtins.objects.dict.PDict;
5660
import com.oracle.graal.python.builtins.objects.function.PKeyword;
5761
import com.oracle.graal.python.builtins.objects.partial.PPartial;
5862
import com.oracle.graal.python.lib.PyCallableCheckNode;
@@ -72,6 +76,7 @@
7276
import com.oracle.truffle.api.dsl.NodeFactory;
7377
import com.oracle.truffle.api.dsl.Specialization;
7478
import com.oracle.truffle.api.frame.VirtualFrame;
79+
import com.oracle.truffle.api.library.CachedLibrary;
7580
import com.oracle.truffle.api.profiles.ConditionProfile;
7681

7782
@CoreFunctions(defineModule = "_functools")
@@ -160,56 +165,87 @@ Object doConvert(Object myCmp) {
160165
"of the given arguments and keywords.\n")
161166
@GenerateNodeFactory
162167
public abstract static class PartialNode extends PythonBuiltinNode {
168+
protected boolean isPartialWithoutDict(GetDictIfExistsNode getDict, Object[] args, HashingStorageLibrary lib, boolean withKwDict) {
169+
return isPartialWithoutDict(getDict, args) && withKwDict == ((PPartial) args[0]).hasKw(lib);
170+
}
171+
163172
protected boolean isPartialWithoutDict(GetDictIfExistsNode getDict, Object[] args) {
164173
return getDict.execute(args[0]) == null && args[0] instanceof PPartial;
165174
}
166175

176+
protected boolean withKeywords(PKeyword[] keywords) {
177+
return keywords.length > 0;
178+
}
179+
167180
protected boolean atLeastOneArg(Object[] args) {
168181
return args.length >= 1;
169182
}
170183

171-
@Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args)"})
172-
Object createFromPartialWoDict(Object cls, Object[] args, PKeyword[] keywords,
184+
@Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lib, false)"})
185+
Object createFromPartialWoDictWoKw(Object cls, Object[] args, PKeyword[] keywords,
173186
@Cached GetDictIfExistsNode getDict,
174187
@Cached ConditionProfile hasArgsProfile,
175-
@Cached ConditionProfile hasKeywordsProfile) {
188+
@Cached ConditionProfile hasKeywordsProfile,
189+
@CachedLibrary(limit = "1") HashingStorageLibrary lib) {
176190
assert args[0] instanceof PPartial;
177191
final PPartial function = (PPartial) args[0];
178-
final Object[] pArgs = function.getArgs();
179-
final PKeyword[] pKeywords = function.getKw();
180-
181-
Object[] newArgs;
182-
if (hasArgsProfile.profile(args.length > 1)) {
183-
newArgs = new Object[pArgs.length + args.length - 1];
184-
PythonUtils.arraycopy(pArgs, 0, newArgs, 0, pArgs.length);
185-
PythonUtils.arraycopy(args, 1, newArgs, pArgs.length, args.length - 1);
186-
} else {
187-
newArgs = pArgs;
188-
}
192+
Object[] funcArgs = getNewPartialArgs(function, args, hasArgsProfile, 1);
189193

190-
PKeyword[] newKeywords;
194+
PDict funcKwDict;
191195
if (hasKeywordsProfile.profile(keywords.length > 0)) {
192-
newKeywords = new PKeyword[pKeywords.length + keywords.length];
193-
PythonUtils.arraycopy(pKeywords, 0, newKeywords, 0, pKeywords.length);
194-
PythonUtils.arraycopy(keywords, 0, newKeywords, pKeywords.length, keywords.length);
196+
funcKwDict = factory().createDict(keywords);
195197
} else {
196-
newKeywords = pKeywords;
198+
funcKwDict = factory().createDict();
197199
}
198200

199-
return factory().createPartial(cls, function.getFn(), newArgs, newKeywords);
201+
return factory().createPartial(cls, function.getFn(), funcArgs, funcKwDict);
202+
}
203+
204+
@Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lib, true)", "!withKeywords(keywords)"})
205+
Object createFromPartialWoDictWKw(Object cls, Object[] args, PKeyword[] keywords,
206+
@Cached GetDictIfExistsNode getDict,
207+
@Cached ConditionProfile hasArgsProfile,
208+
@CachedLibrary(limit = "1") HashingStorageLibrary lib) {
209+
assert args[0] instanceof PPartial;
210+
final PPartial function = (PPartial) args[0];
211+
Object[] funcArgs = getNewPartialArgs(function, args, hasArgsProfile, 1);
212+
return factory().createPartial(cls, function.getFn(), funcArgs, function.getKwCopy(factory(), lib));
213+
}
214+
215+
@Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lib, true)", "withKeywords(keywords)"})
216+
Object createFromPartialWoDictWKwKw(VirtualFrame frame, Object cls, Object[] args, PKeyword[] keywords,
217+
@Cached GetDictIfExistsNode getDict,
218+
@Cached ConditionProfile hasArgsProfile,
219+
@Cached HashingStorage.InitNode initNode,
220+
@CachedLibrary(limit = "1") HashingStorageLibrary lib) {
221+
assert args[0] instanceof PPartial;
222+
final PPartial function = (PPartial) args[0];
223+
Object[] funcArgs = getNewPartialArgs(function, args, hasArgsProfile, 1);
224+
225+
HashingStorage storage = function.getKw().getDictStorage();
226+
storage = lib.addAllToOther(initNode.execute(frame, PNone.NO_VALUE, keywords), storage);
227+
228+
return factory().createPartial(cls, function.getFn(), funcArgs, factory().createDict(storage));
200229
}
201230

202231
@Specialization(guards = {"atLeastOneArg(args)", "!isPartialWithoutDict(getDict, args)"})
203232
Object createGeneric(Object cls, Object[] args, PKeyword[] keywords,
204233
@Cached GetDictIfExistsNode getDict,
234+
@Cached ConditionProfile hasKeywordsProfile,
205235
@Cached PyCallableCheckNode callableCheckNode) {
206236
Object function = args[0];
207237
if (!callableCheckNode.execute(function)) {
208238
throw raise(PythonBuiltinClassType.TypeError, S_ARG_MUST_BE_CALLABLE, "the first");
209239
}
210240

211241
final Object[] funcArgs = PythonUtils.arrayCopyOfRange(args, 1, args.length);
212-
return factory().createPartial(cls, function, funcArgs, keywords);
242+
PDict funcKwDict;
243+
if (hasKeywordsProfile.profile(keywords.length > 0)) {
244+
funcKwDict = factory().createDict(keywords);
245+
} else {
246+
funcKwDict = factory().createDict();
247+
}
248+
return factory().createPartial(cls, function, funcArgs, funcKwDict);
213249
}
214250

215251
@Specialization(guards = "!atLeastOneArg(args)")

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/partial/PPartial.java

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,22 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.partial;
4242

43+
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
4344
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
4445
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
4546
import com.oracle.graal.python.builtins.objects.dict.PDict;
46-
import com.oracle.graal.python.builtins.objects.function.PKeyword;
4747
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
4848
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
49-
import com.oracle.graal.python.nodes.argument.keywords.ExpandKeywordStarargsNode;
5049
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
5150
import com.oracle.truffle.api.object.Shape;
5251

5352
public final class PPartial extends PythonBuiltinObject {
5453
private Object fn;
5554
private Object[] args;
5655
private PTuple argsTuple;
57-
private PKeyword[] kw;
58-
private PDict kwDict;
56+
private PDict kw;
5957

60-
public PPartial(Object cls, Shape instanceShape, Object fn, Object[] args, PKeyword[] kw) {
58+
public PPartial(Object cls, Shape instanceShape, Object fn, Object[] args, PDict kw) {
6159
super(cls, instanceShape);
6260
this.fn = fn;
6361
this.args = args;
@@ -88,19 +86,27 @@ public void setArgs(PTuple args, SequenceNodes.GetSequenceStorageNode storageNod
8886
this.args = arrayNode.execute(storageNode.execute(args));
8987
}
9088

91-
public PKeyword[] getKw() {
89+
public PDict getKw() {
9290
return kw;
9391
}
94-
95-
public PDict getKwDict(PythonObjectFactory factory) {
96-
if (kwDict == null) {
97-
this.kwDict = factory.createDict(kw);
92+
93+
public PDict getOrCreateKw(PythonObjectFactory factory) {
94+
if (kw == null) {
95+
kw = factory.createDict();
9896
}
99-
return kwDict;
97+
return kw;
98+
}
99+
100+
public PDict getKwCopy(PythonObjectFactory factory, HashingStorageLibrary lib) {
101+
assert kw != null;
102+
return factory.createDict(lib.copy(kw.getDictStorage()));
103+
}
104+
105+
public boolean hasKw(HashingStorageLibrary lib) {
106+
return lib.length(kw.getDictStorage()) > 0;
100107
}
101108

102-
public void setKw(PDict kwArgs, ExpandKeywordStarargsNode expandNode) {
103-
this.kwDict = kwArgs;
104-
this.kw = expandNode.execute(kwArgs);
109+
public void setKwCopy(PDict kwArgs, PythonObjectFactory factory, HashingStorageLibrary lib) {
110+
this.kw = factory.createDict(lib.copy(kwArgs.getDictStorage()));
105111
}
106112
}

0 commit comments

Comments
 (0)