Skip to content

Commit 2c75d0d

Browse files
committed
intrinsified itertools.combinations/combinations_with_replace()
1 parent 72da0f9 commit 2c75d0d

File tree

9 files changed

+693
-102
lines changed

9 files changed

+693
-102
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@
197197
import com.oracle.graal.python.builtins.objects.iterator.SentinelIteratorBuiltins;
198198
import com.oracle.graal.python.builtins.objects.itertools.AccumulateBuiltins;
199199
import com.oracle.graal.python.builtins.objects.itertools.ChainBuiltins;
200+
import com.oracle.graal.python.builtins.objects.itertools.CombinationsBuiltins;
200201
import com.oracle.graal.python.builtins.objects.itertools.CompressBuiltins;
201202
import com.oracle.graal.python.builtins.objects.itertools.CountBuiltins;
202203
import com.oracle.graal.python.builtins.objects.itertools.DropwhileBuiltins;
@@ -512,6 +513,7 @@ private static PythonBuiltins[] initializeBuiltins(boolean nativeAccessAllowed)
512513

513514
// itertools
514515
new AccumulateBuiltins(),
516+
new CombinationsBuiltins(),
515517
new CompressBuiltins(),
516518
new DropwhileBuiltins(),
517519
new ChainBuiltins(),

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ public enum PythonBuiltinClassType implements TruffleObject {
212212
PTee("_tee", "itertools", Flags.PUBLIC_DERIVED_WODICT),
213213
PTeeDataObject("_tee_dataobject", "itertools", Flags.PUBLIC_DERIVED_WODICT),
214214
PAccumulate("accumulate", "itertools"),
215+
PCombinations("combinations", "itertools"),
216+
PCombinationsWithReplacement("combinations_with_replacement", "itertools"),
215217
PCompress("compress", "itertools"),
216218
PDropwhile("dropwhile", "itertools"),
217219
PFilterfalse("filterfalse", "itertools"),

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import com.oracle.graal.python.builtins.objects.function.PKeyword;
4242
import com.oracle.graal.python.builtins.objects.itertools.PAccumulate;
4343
import com.oracle.graal.python.builtins.objects.itertools.PChain;
44+
import com.oracle.graal.python.builtins.objects.itertools.PCombinations;
45+
import com.oracle.graal.python.builtins.objects.itertools.PCombinationsWithReplacement;
4446
import com.oracle.graal.python.builtins.objects.itertools.PCompress;
4547
import com.oracle.graal.python.builtins.objects.itertools.PCount;
4648
import com.oracle.graal.python.builtins.objects.itertools.PDropwhile;
@@ -61,6 +63,7 @@
6163
import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode;
6264
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
6365
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
66+
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryClinicBuiltinNode;
6467
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
6568
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
6669
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
@@ -99,6 +102,64 @@ protected Object notype(Object cls, Object[] arguments, PKeyword[] keywords,
99102
}
100103
}
101104

105+
@Builtin(name = "combinations", minNumOfPositionalArgs = 3, constructsClass = PythonBuiltinClassType.PCombinations, parameterNames = {"$self", "iterable",
106+
"r"}, doc = "combinations(iterable, r) --> combinations object\n\n" +
107+
"Return successive r-length combinations of elements in the iterable.\n\n" +
108+
"combinations(range(4), 3) --> (0,1,2), (0,1,3), (0,2,3), (1,2,3)")
109+
@ArgumentClinic(name = "r", conversion = ArgumentClinic.ClinicConversion.Int)
110+
@GenerateNodeFactory
111+
public abstract static class CombinationsNode extends PythonTernaryClinicBuiltinNode {
112+
113+
@Override
114+
protected ArgumentClinicProvider getArgumentClinic() {
115+
return ItertoolsModuleBuiltinsClinicProviders.CombinationsNodeClinicProviderGen.INSTANCE;
116+
}
117+
118+
@SuppressWarnings("unused")
119+
@Specialization(guards = "isTypeNode.execute(cls)", limit = "1")
120+
protected PCombinations construct(Object cls, Object iterable, int r,
121+
@Cached TypeNodes.IsTypeNode isTypeNode) {
122+
return factory().createCombinations();
123+
}
124+
125+
@SuppressWarnings("unused")
126+
@Specialization(guards = "!isTypeNode.execute(cls)")
127+
protected Object notype(Object cls, Object iterable, Object r,
128+
@SuppressWarnings("unused") @Cached TypeNodes.IsTypeNode isTypeNode) {
129+
throw raise(TypeError, ErrorMessages.IS_NOT_TYPE_OBJ, "'cls'", cls);
130+
}
131+
}
132+
133+
// XXX this vs. init?
134+
@Builtin(name = "combinations_with_replacement", minNumOfPositionalArgs = 3, constructsClass = PythonBuiltinClassType.PCombinationsWithReplacement, parameterNames = {"$self", "iterable",
135+
"r"}, doc = "combinations_with_replacement(iterable, r) --> combinations_with_replacement object\n\n" +
136+
"Return successive r-length combinations of elements in the iterable\n" +
137+
"allowing individual elements to have successive repeats.\n" +
138+
" combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC")
139+
@ArgumentClinic(name = "r", conversion = ArgumentClinic.ClinicConversion.Int)
140+
@GenerateNodeFactory
141+
public abstract static class CombinationsWithReplacementNode extends PythonTernaryClinicBuiltinNode {
142+
143+
@Override
144+
protected ArgumentClinicProvider getArgumentClinic() {
145+
return ItertoolsModuleBuiltinsClinicProviders.CombinationsNodeClinicProviderGen.INSTANCE;
146+
}
147+
148+
@SuppressWarnings("unused")
149+
@Specialization(guards = "isTypeNode.execute(cls)", limit = "1")
150+
protected PCombinationsWithReplacement construct(Object cls, Object iterable, int r,
151+
@Cached TypeNodes.IsTypeNode isTypeNode) {
152+
return factory().createCombinationsWithReplacement();
153+
}
154+
155+
@SuppressWarnings("unused")
156+
@Specialization(guards = "!isTypeNode.execute(cls)")
157+
protected Object notype(Object cls, Object iterable, Object r,
158+
@SuppressWarnings("unused") @Cached TypeNodes.IsTypeNode isTypeNode) {
159+
throw raise(TypeError, ErrorMessages.IS_NOT_TYPE_OBJ, "'cls'", cls);
160+
}
161+
}
162+
102163
@Builtin(name = "compress", minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true, constructsClass = PythonBuiltinClassType.PCompress, doc = "Make an iterator that filters elements from *data* returning\n" +
103164
"only those that have a corresponding element in *selectors* that evaluates to\n" +
104165
"``True``. Stops when either the *data* or *selectors* iterables has been\n" +
@@ -345,6 +406,9 @@ protected Object construct(Object cls, Object[] arguments, PKeyword[] keywords)
345406
}
346407
}
347408

409+
// XXX all c-tors should implement what is done in init and remove init, it is a noop in python
410+
// too
411+
// XXX add tests for it
348412
@Builtin(name = "repeat", minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true, constructsClass = PythonBuiltinClassType.PRepeat, doc = "repeat(object [,times]) -> create an iterator which returns the object\n" +
349413
"for the specified number of times. If not specified, returns the object\nendlessly.")
350414
@GenerateNodeFactory

0 commit comments

Comments
 (0)