|
41 | 41 | package com.oracle.graal.python.builtins.modules.functools; |
42 | 42 |
|
43 | 43 | import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PythonObject; |
44 | | -import static com.oracle.graal.python.nodes.BuiltinNames.J_PARTIAL; |
| 44 | +import static com.oracle.graal.python.nodes.BuiltinNames.J_FUNCTOOLS; |
45 | 45 | import static com.oracle.graal.python.nodes.ErrorMessages.REDUCE_EMPTY_SEQ; |
46 | | -import static com.oracle.graal.python.nodes.ErrorMessages.S_ARG_MUST_BE_CALLABLE; |
47 | 46 | import static com.oracle.graal.python.nodes.ErrorMessages.S_ARG_N_MUST_SUPPORT_ITERATION; |
48 | | -import static com.oracle.graal.python.nodes.ErrorMessages.TYPE_S_TAKES_AT_LEAST_ONE_ARGUMENT; |
49 | | -import static com.oracle.graal.python.nodes.SpecialMethodNames.J___INIT__; |
50 | 47 | import static com.oracle.truffle.api.nodes.LoopNode.reportLoopCount; |
51 | 48 |
|
52 | 49 | import java.util.List; |
53 | 50 |
|
54 | 51 | import com.oracle.graal.python.builtins.Builtin; |
55 | 52 | import com.oracle.graal.python.builtins.CoreFunctions; |
| 53 | +import com.oracle.graal.python.builtins.Python3Core; |
56 | 54 | import com.oracle.graal.python.builtins.PythonBuiltinClassType; |
57 | 55 | import com.oracle.graal.python.builtins.PythonBuiltins; |
58 | | -import com.oracle.graal.python.builtins.objects.PNone; |
59 | | -import com.oracle.graal.python.builtins.objects.common.HashingStorage; |
60 | | -import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageAddAllToOther; |
61 | | -import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageCopy; |
62 | | -import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageLen; |
63 | | -import com.oracle.graal.python.builtins.objects.dict.PDict; |
64 | | -import com.oracle.graal.python.builtins.objects.function.PKeyword; |
65 | 56 | import com.oracle.graal.python.lib.GetNextNode; |
66 | | -import com.oracle.graal.python.lib.PyCallableCheckNode; |
67 | 57 | import com.oracle.graal.python.lib.PyObjectGetIter; |
68 | 58 | import com.oracle.graal.python.nodes.PGuards; |
| 59 | +import com.oracle.graal.python.nodes.SpecialAttributeNames; |
69 | 60 | import com.oracle.graal.python.nodes.call.CallNode; |
70 | 61 | import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; |
71 | | -import com.oracle.graal.python.nodes.function.PythonBuiltinNode; |
72 | 62 | import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode; |
73 | 63 | import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode; |
74 | 64 | import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile; |
75 | | -import com.oracle.graal.python.nodes.object.GetDictIfExistsNode; |
76 | 65 | import com.oracle.graal.python.runtime.exception.PException; |
77 | | -import com.oracle.graal.python.util.PythonUtils; |
78 | 66 | import com.oracle.truffle.api.CompilerDirectives; |
79 | | -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; |
80 | 67 | import com.oracle.truffle.api.dsl.Bind; |
81 | 68 | import com.oracle.truffle.api.dsl.Cached; |
82 | 69 | import com.oracle.truffle.api.dsl.GenerateNodeFactory; |
83 | 70 | import com.oracle.truffle.api.dsl.NodeFactory; |
84 | 71 | import com.oracle.truffle.api.dsl.Specialization; |
85 | 72 | import com.oracle.truffle.api.frame.VirtualFrame; |
86 | 73 | import com.oracle.truffle.api.nodes.Node; |
| 74 | +import com.oracle.truffle.api.object.HiddenKey; |
87 | 75 | import com.oracle.truffle.api.profiles.InlinedConditionProfile; |
88 | 76 |
|
89 | | -@CoreFunctions(defineModule = "_functools") |
| 77 | +@CoreFunctions(defineModule = J_FUNCTOOLS) |
90 | 78 | public final class FunctoolsModuleBuiltins extends PythonBuiltins { |
91 | 79 | @Override |
92 | 80 | protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() { |
93 | 81 | return FunctoolsModuleBuiltinsFactory.getFactories(); |
94 | 82 | } |
95 | 83 |
|
| 84 | + protected static final HiddenKey KWD_MARK = new HiddenKey("kwd_mark"); |
| 85 | + |
| 86 | + @Override |
| 87 | + public void initialize(Python3Core core) { |
| 88 | + super.initialize(core); |
| 89 | + addBuiltinConstant(SpecialAttributeNames.T___DOC__, |
| 90 | + "Create a cached callable that wraps another function.\n" + // |
| 91 | + "\n" + // |
| 92 | + "user_function: the function being cached\n" + // |
| 93 | + "\n" + // |
| 94 | + "maxsize: 0 for no caching\n" + // |
| 95 | + " None for unlimited cache size\n" + // |
| 96 | + " n for a bounded cache\n" + // |
| 97 | + "\n" + // |
| 98 | + "typed: False cache f(3) and f(3.0) as identical calls\n" + // |
| 99 | + " True cache f(3) and f(3.0) as distinct calls\n" + // |
| 100 | + "\n" + // |
| 101 | + "cache_info_type: namedtuple class with the fields:\n" + // |
| 102 | + " hits misses currsize maxsize\n"); |
| 103 | + addBuiltinConstant(KWD_MARK, core.factory().createPythonObject(PythonObject)); |
| 104 | + } |
| 105 | + |
96 | 106 | // functools.reduce(function, iterable[, initializer]) |
97 | 107 | @Builtin(name = "reduce", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3, doc = "reduce(function, sequence[, initial]) -> value\n" + |
98 | 108 | "\n" + |
@@ -165,171 +175,4 @@ Object doConvert(Object myCmp) { |
165 | 175 | } |
166 | 176 | } |
167 | 177 |
|
168 | | - // functools.partial(func, /, *args, **keywords) |
169 | | - @Builtin(name = J_PARTIAL, minNumOfPositionalArgs = 1, varArgsMarker = true, takesVarArgs = true, takesVarKeywordArgs = true, constructsClass = PythonBuiltinClassType.PPartial, doc = "partial(func, *args, **keywords) - new function with partial application\n" + |
170 | | - "of the given arguments and keywords.\n") |
171 | | - @GenerateNodeFactory |
172 | | - public abstract static class PartialNode extends PythonBuiltinNode { |
173 | | - protected boolean isPartialWithoutDict(GetDictIfExistsNode getDict, Object[] args, HashingStorageLen lenNode, boolean withKwDict) { |
174 | | - return isPartialWithoutDict(getDict, args) && withKwDict == ((PPartial) args[0]).hasKw(lenNode); |
175 | | - } |
176 | | - |
177 | | - protected boolean isPartialWithoutDict(GetDictIfExistsNode getDict, Object[] args) { |
178 | | - return getDict.execute(args[0]) == null && args[0] instanceof PPartial; |
179 | | - } |
180 | | - |
181 | | - protected boolean withKeywords(PKeyword[] keywords) { |
182 | | - return keywords.length > 0; |
183 | | - } |
184 | | - |
185 | | - protected boolean atLeastOneArg(Object[] args) { |
186 | | - return args.length >= 1; |
187 | | - } |
188 | | - |
189 | | - @Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lenNode, false)"}, limit = "1") |
190 | | - @SuppressWarnings("truffle-static-method") |
191 | | - Object createFromPartialWoDictWoKw(Object cls, Object[] args, PKeyword[] keywords, |
192 | | - @Bind("this") Node inliningTarget, |
193 | | - @SuppressWarnings("unused") @Cached GetDictIfExistsNode getDict, |
194 | | - @Cached InlinedConditionProfile hasArgsProfile, |
195 | | - @Cached InlinedConditionProfile hasKeywordsProfile, |
196 | | - @SuppressWarnings("unused") @Cached HashingStorageLen lenNode) { |
197 | | - assert args[0] instanceof PPartial; |
198 | | - final PPartial function = (PPartial) args[0]; |
199 | | - Object[] funcArgs = getNewPartialArgs(function, args, inliningTarget, hasArgsProfile, 1); |
200 | | - |
201 | | - PDict funcKwDict; |
202 | | - if (hasKeywordsProfile.profile(inliningTarget, keywords.length > 0)) { |
203 | | - funcKwDict = factory().createDict(keywords); |
204 | | - } else { |
205 | | - funcKwDict = factory().createDict(); |
206 | | - } |
207 | | - |
208 | | - return factory().createPartial(cls, function.getFn(), funcArgs, funcKwDict); |
209 | | - } |
210 | | - |
211 | | - @Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lenNode, true)", "!withKeywords(keywords)"}, limit = "1") |
212 | | - @SuppressWarnings("truffle-static-method") |
213 | | - Object createFromPartialWoDictWKw(Object cls, Object[] args, @SuppressWarnings("unused") PKeyword[] keywords, |
214 | | - @Bind("this") Node inliningTarget, |
215 | | - @SuppressWarnings("unused") @Cached GetDictIfExistsNode getDict, |
216 | | - @Cached InlinedConditionProfile hasArgsProfile, |
217 | | - @SuppressWarnings("unused") @Cached HashingStorageLen lenNode, |
218 | | - @Cached HashingStorageCopy copyNode) { |
219 | | - assert args[0] instanceof PPartial; |
220 | | - final PPartial function = (PPartial) args[0]; |
221 | | - Object[] funcArgs = getNewPartialArgs(function, args, inliningTarget, hasArgsProfile, 1); |
222 | | - return factory().createPartial(cls, function.getFn(), funcArgs, function.getKwCopy(factory(), copyNode)); |
223 | | - } |
224 | | - |
225 | | - @Specialization(guards = {"atLeastOneArg(args)", "isPartialWithoutDict(getDict, args, lenNode, true)", "withKeywords(keywords)"}, limit = "1") |
226 | | - @SuppressWarnings("truffle-static-method") |
227 | | - Object createFromPartialWoDictWKwKw(VirtualFrame frame, Object cls, Object[] args, PKeyword[] keywords, |
228 | | - @Bind("this") Node inliningTarget, |
229 | | - @SuppressWarnings("unused") @Cached GetDictIfExistsNode getDict, |
230 | | - @Cached InlinedConditionProfile hasArgsProfile, |
231 | | - @Cached HashingStorage.InitNode initNode, |
232 | | - @SuppressWarnings("unused") @Cached HashingStorageLen lenNode, |
233 | | - @Cached HashingStorageCopy copyHashingStorageNode, |
234 | | - @Cached HashingStorageAddAllToOther addAllToOtherNode) { |
235 | | - assert args[0] instanceof PPartial; |
236 | | - final PPartial function = (PPartial) args[0]; |
237 | | - Object[] funcArgs = getNewPartialArgs(function, args, inliningTarget, hasArgsProfile, 1); |
238 | | - |
239 | | - HashingStorage storage = copyHashingStorageNode.execute(function.getKw().getDictStorage()); |
240 | | - PDict result = factory().createDict(storage); |
241 | | - addAllToOtherNode.execute(frame, initNode.execute(frame, PNone.NO_VALUE, keywords), result); |
242 | | - |
243 | | - return factory().createPartial(cls, function.getFn(), funcArgs, result); |
244 | | - } |
245 | | - |
246 | | - @Specialization(guards = {"atLeastOneArg(args)", "!isPartialWithoutDict(getDict, args)"}, limit = "1") |
247 | | - @SuppressWarnings("truffle-static-method") |
248 | | - Object createGeneric(Object cls, Object[] args, PKeyword[] keywords, |
249 | | - @Bind("this") Node inliningTarget, |
250 | | - @SuppressWarnings("unused") @Cached GetDictIfExistsNode getDict, |
251 | | - @Cached InlinedConditionProfile hasKeywordsProfile, |
252 | | - @Cached PyCallableCheckNode callableCheckNode) { |
253 | | - Object function = args[0]; |
254 | | - if (!callableCheckNode.execute(function)) { |
255 | | - throw raise(PythonBuiltinClassType.TypeError, S_ARG_MUST_BE_CALLABLE, "the first"); |
256 | | - } |
257 | | - |
258 | | - final Object[] funcArgs = PythonUtils.arrayCopyOfRange(args, 1, args.length); |
259 | | - PDict funcKwDict; |
260 | | - if (hasKeywordsProfile.profile(inliningTarget, keywords.length > 0)) { |
261 | | - funcKwDict = factory().createDict(keywords); |
262 | | - } else { |
263 | | - funcKwDict = factory().createDict(); |
264 | | - } |
265 | | - return factory().createPartial(cls, function, funcArgs, funcKwDict); |
266 | | - } |
267 | | - |
268 | | - @Specialization(guards = "!atLeastOneArg(args)") |
269 | | - @SuppressWarnings("unused") |
270 | | - Object noCallable(Object cls, Object[] args, PKeyword[] keywords) { |
271 | | - throw raise(PythonBuiltinClassType.TypeError, TYPE_S_TAKES_AT_LEAST_ONE_ARGUMENT, "partial"); |
272 | | - } |
273 | | - } |
274 | | -} |
275 | | - |
276 | | -@CoreFunctions(extendClasses = PythonBuiltinClassType.LsprofProfiler) |
277 | | -class ProfilerBuiltins extends PythonBuiltins { |
278 | | - @Override |
279 | | - protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() { |
280 | | - return ProfilerBuiltinsFactory.getFactories(); |
281 | | - } |
282 | | - |
283 | | - @Builtin(name = J___INIT__, minNumOfPositionalArgs = 1, parameterNames = {"$self", "timer", "timeunit", "subcalls", "builtins"}) |
284 | | - @GenerateNodeFactory |
285 | | - abstract static class Init extends PythonBuiltinNode { |
286 | | - @Specialization |
287 | | - PNone doit(Profiler self, Object timer, double timeunit, long subcalls, long builtins) { |
288 | | - self.subcalls = subcalls > 0; |
289 | | - self.builtins = builtins > 0; |
290 | | - self.timeunit = timeunit; |
291 | | - self.externalTimer = timer; |
292 | | - return PNone.NONE; |
293 | | - } |
294 | | - |
295 | | - @Specialization |
296 | | - @SuppressWarnings("unused") |
297 | | - PNone doit(Profiler self, Object timer, PNone timeunit, PNone subcalls, PNone builtins) { |
298 | | - self.subcalls = true; |
299 | | - self.builtins = true; |
300 | | - self.timeunit = -1; |
301 | | - self.externalTimer = timer; |
302 | | - return PNone.NONE; |
303 | | - } |
304 | | - } |
305 | | - |
306 | | - @Builtin(name = "enable", minNumOfPositionalArgs = 1, parameterNames = {"$self", "subcalls", "builtins"}) |
307 | | - @GenerateNodeFactory |
308 | | - abstract static class Enable extends PythonBuiltinNode { |
309 | | - @Specialization |
310 | | - @TruffleBoundary |
311 | | - PNone doit(Profiler self, long subcalls, long builtins) { |
312 | | - self.subcalls = subcalls > 0; |
313 | | - self.builtins = builtins > 0; |
314 | | - // TODO: deal with any arguments |
315 | | - self.time = System.currentTimeMillis(); |
316 | | - self.sampler.setCollecting(true); |
317 | | - return PNone.NONE; |
318 | | - } |
319 | | - |
320 | | - @Specialization |
321 | | - PNone doit(Profiler self, long subcalls, @SuppressWarnings("unused") PNone builtins) { |
322 | | - return doit(self, subcalls, self.builtins ? 1 : 0); |
323 | | - } |
324 | | - |
325 | | - @Specialization |
326 | | - PNone doit(Profiler self, @SuppressWarnings("unused") PNone subcalls, long builtins) { |
327 | | - return doit(self, self.subcalls ? 1 : 0, builtins); |
328 | | - } |
329 | | - |
330 | | - @Specialization |
331 | | - PNone doit(Profiler self, @SuppressWarnings("unused") PNone subcalls, @SuppressWarnings("unused") PNone builtins) { |
332 | | - return doit(self, self.subcalls ? 1 : 0, self.builtins ? 1 : 0); |
333 | | - } |
334 | | - } |
335 | 178 | } |
0 commit comments