@@ -35,27 +35,38 @@ public final class ArgumentConstraints {
35
35
private static final String EXPRESSION_TYPE = "expression" ;
36
36
37
37
/**
38
- * Describes a heterogenous list of arguments. Each argument is checked against
38
+ * Describes a heterogeneous list of arguments. Each argument is checked against
39
39
* the corresponding constraint. An {@link ArityException} will be thrown when
40
40
* the number of arguments does not exactly match the number of constraints.
41
41
* <p>
42
42
* May only be used as a top level constraint – and is already built in to
43
43
* {@link Function}, so direct usage of this method should not be needed.
44
44
*/
45
45
public static ArgumentConstraint listOf (ArgumentConstraint ... constraints ) {
46
- return new HeterogenousListOf (constraints );
46
+ return new HeterogeneousListOf (constraints );
47
47
}
48
48
49
49
/**
50
- * Descripes a homogenous list of arguments, of fixed or variable length.
50
+ * Describes a homogeneous list of arguments, of fixed or variable length.
51
51
* An {@link ArityException} will be thrown when there are fewer arguments
52
52
* than the specified minimum arity, or when there are more arguments than
53
53
* the specified maximum arity.
54
54
* <p>
55
55
* May only be used as a top level constraint.
56
56
*/
57
57
public static ArgumentConstraint listOf (int min , int max , ArgumentConstraint constraint ) {
58
- return new HomogenousListOf (min , max , constraint );
58
+ return new HomogeneousListOf (min , max , constraint );
59
+ }
60
+
61
+ /**
62
+ * Describes a homogeneous list of arguments without upper limit.
63
+ * An {@link ArityException} will be thrown when there are fewer arguments
64
+ * than the specified minimum arity.
65
+ * <p>
66
+ * May only be used as a top level constraint.
67
+ */
68
+ public static ArgumentConstraint listOf (int min , ArgumentConstraint constraint ) {
69
+ return new VariadicListOf (min , constraint );
59
70
}
60
71
61
72
/**
@@ -115,7 +126,7 @@ public BaseArgumentConstraint(int minArity, int maxArity, String expectedTypeDes
115
126
this .expectedTypeDescription = expectedTypeDescription ;
116
127
}
117
128
118
- protected <T > Iterator <ArgumentError > checkNoRemaingArguments (Iterator <FunctionArgument <T >> arguments , boolean expectNoRemainingArguments ) {
129
+ protected <T > Iterator <ArgumentError > checkNoRemainingArguments (Iterator <FunctionArgument <T >> arguments , boolean expectNoRemainingArguments ) {
119
130
if (expectNoRemainingArguments && arguments .hasNext ()) {
120
131
return singletonIterator (ArgumentError .createArityError ());
121
132
} else {
@@ -133,6 +144,9 @@ public int maxArity() {
133
144
return maxArity ;
134
145
}
135
146
147
+ @ Override
148
+ public boolean arityViolated (int n ) { return (n < minArity || maxArity < n ); }
149
+
136
150
@ Override
137
151
public String expectedType () {
138
152
return expectedTypeDescription ;
@@ -147,10 +161,10 @@ protected <U> Iterator<U> emptyIterator() {
147
161
}
148
162
}
149
163
150
- private static class HomogenousListOf extends BaseArgumentConstraint {
164
+ private static class HomogeneousListOf extends BaseArgumentConstraint {
151
165
private final ArgumentConstraint subConstraint ;
152
166
153
- public HomogenousListOf (int minArity , int maxArity , ArgumentConstraint subConstraint ) {
167
+ public HomogeneousListOf (int minArity , int maxArity , ArgumentConstraint subConstraint ) {
154
168
super (minArity , maxArity , subConstraint .expectedType ());
155
169
this .subConstraint = subConstraint ;
156
170
}
@@ -178,14 +192,14 @@ public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionAr
178
192
break ;
179
193
}
180
194
}
181
- return checkNoRemaingArguments (arguments , expectNoRemainingArguments );
195
+ return checkNoRemainingArguments (arguments , expectNoRemainingArguments );
182
196
}
183
197
}
184
198
185
- private static class HeterogenousListOf extends BaseArgumentConstraint {
199
+ private static class HeterogeneousListOf extends BaseArgumentConstraint {
186
200
private final ArgumentConstraint [] subConstraints ;
187
201
188
- public HeterogenousListOf (ArgumentConstraint [] subConstraints ) {
202
+ public HeterogeneousListOf (ArgumentConstraint [] subConstraints ) {
189
203
super (calculateMinArity (subConstraints ), calculateMaxArity (subConstraints ), null );
190
204
this .subConstraints = subConstraints ;
191
205
}
@@ -218,10 +232,39 @@ public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionAr
218
232
return singletonIterator (ArgumentError .createArityError ());
219
233
}
220
234
}
221
- return checkNoRemaingArguments (arguments , expectNoRemainingArguments );
235
+ return checkNoRemainingArguments (arguments , expectNoRemainingArguments );
236
+ }
237
+ }
238
+
239
+ private static class VariadicListOf extends BaseArgumentConstraint {
240
+ private final ArgumentConstraint subConstraint ;
241
+
242
+ public VariadicListOf (int minArity , ArgumentConstraint subConstraint ) {
243
+ super (minArity , -1 , subConstraint .expectedType ());
244
+ this .subConstraint = subConstraint ;
245
+ }
246
+
247
+ @ Override
248
+ public <T > Iterator <ArgumentError > check (Adapter <T > runtime , Iterator <FunctionArgument <T >> arguments , boolean expectNoRemainingArguments ) {
249
+ int i = 0 ;
250
+ for ( ;arguments .hasNext (); ++i ) {
251
+ Iterator <ArgumentError > error = subConstraint .check (runtime , arguments , false );
252
+ if (error .hasNext ()) {
253
+ return error ;
254
+ }
255
+ }
256
+ if (i < minArity ()) {
257
+ return singletonIterator (ArgumentError .createArityError ());
258
+ } else {
259
+ return emptyIterator ();
260
+ }
222
261
}
262
+
263
+ @ Override
264
+ public boolean arityViolated (int n ) { return n < minArity (); }
223
265
}
224
266
267
+
225
268
private static abstract class TypeCheck extends BaseArgumentConstraint {
226
269
public TypeCheck (String expectedType ) {
227
270
super (1 , 1 , expectedType );
@@ -234,7 +277,7 @@ public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionAr
234
277
if (error .hasNext ()) {
235
278
return error ;
236
279
} else {
237
- return checkNoRemaingArguments (arguments , expectNoRemainingArguments );
280
+ return checkNoRemainingArguments (arguments , expectNoRemainingArguments );
238
281
}
239
282
} else {
240
283
return singletonIterator (ArgumentError .createArityError ());
@@ -359,7 +402,7 @@ public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionAr
359
402
return singletonIterator ((ArgumentError ) ArgumentError .createArgumentTypeError (expectedType (), type .toString ()));
360
403
}
361
404
}
362
- return checkNoRemaingArguments (arguments , expectNoRemainingArguments );
405
+ return checkNoRemainingArguments (arguments , expectNoRemainingArguments );
363
406
} else {
364
407
return singletonIterator (ArgumentError .createArityError ());
365
408
}
0 commit comments