001 package edu.rice.cs.cunit.util;
002
003 import java.util.Arrays;
004 import java.util.LinkedList;
005
006 /**
007 * Unary lambda interface R <- P.
008 * @author Mathias Ricken
009 */
010 public interface ILambda<R, P> {
011 /**
012 * Apply the lambda.
013 * @param param lambda-specific parameter
014 * @return lambda-specific return value
015 */
016 public abstract R apply(P param);
017
018 /**
019 * Binary lambda interface R <- P x Q.
020 */
021 public static interface Binary<R, P, Q> {
022 /**
023 * Apply the lambda.
024 * @param param1 lambda-specific first parameter
025 * @param param2 lambda-specific second parameter
026 * @return lambda-specific return value
027 */
028 public abstract R apply(P param1, Q param2);
029
030 /**
031 * Unary decorator for a binary lambda that binds a constant to its first parameter.
032 */
033 public static class Bind1st<R, P, Q> implements ILambda<R, Q> {
034 /**
035 * The constant first argument.
036 */
037 private P _constant;
038
039 /**
040 * The binary lambda that is decorated.
041 */
042 private ILambda.Binary<R, P, Q> _decoree;
043
044 /**
045 * Create a new unary decorator for a binary lambda, binding a constant to its first parameter.
046 * @param decoree binary lambda
047 * @param constant constant for the binary lambda's first parameter
048 */
049 public Bind1st(Binary<R, P, Q> decoree, P constant) {
050 _constant = constant;
051 _decoree = decoree;
052 }
053
054 /**
055 * Apply the unary decorator, i.e. apply the constant and the parameter to the binary lambda.
056 * @param param argument for the binary lambda's second parameter
057 * @return return value of the binary lambda
058 */
059 public R apply(Q param) {
060 return _decoree.apply(_constant, param);
061 }
062 }
063
064 /**
065 * Unary decorator for a binary lambda that binds a constant to its second parameter.
066 */
067 public static class Bind2nd<R, P, Q> implements ILambda<R, P> {
068 /**
069 * The constant second argument.
070 */
071 private Q _constant;
072
073 /**
074 * The binary lambda that is decorated.
075 */
076 private ILambda.Binary<R, P, Q> _decoree;
077
078 /**
079 * Create a new unary decorator for a binary lambda, binding a constant to its second parameter.
080 * @param decoree binary lambda
081 * @param constant constant for the binary lambda's second parameter
082 */
083 public Bind2nd(Binary<R, P, Q> decoree, Q constant) {
084 _constant = constant;
085 _decoree = decoree;
086 }
087
088 /**
089 * Apply the unary decorator, i.e. apply the parameter and the constant to the binary lambda.
090 * @param param argument for the binary lambda's first parameter
091 * @return return value of the binary lambda
092 */
093 public R apply(P param) {
094 return _decoree.apply(param, _constant);
095 }
096 }
097
098 /**
099 * Adapter to turn an N-ary lambda into a binary lambda.
100 */
101 public static class NaryAdaptor<R, P> implements ILambda.Binary<R, P, P> {
102 /**
103 * The N-ary lambda.
104 */
105 private ILambda.Nary<R, P> _decoree;
106
107 /**
108 * Creates a new binary lambda.
109 * @param decoree N-ary lambda
110 */
111 public NaryAdaptor(ILambda.Nary<R, P> decoree) {
112 _decoree = decoree;
113 }
114
115 /**
116 * Apply the N-ary lambda.
117 * @param param1 the first parameter.
118 * @param param2 the second parameter.
119 * @return return value of the N-ary lambda
120 */
121 public R apply(P param1, P param2) {
122 @SuppressWarnings("unchecked") R retval = _decoree.apply(param1, param2);
123 return retval;
124 }
125 }
126
127 /**
128 * Binary maximum.
129 */
130 public static class Max<T extends Comparable<T>> implements ILambda.Binary<T, T, T> {
131 public T apply(T param1, T param2) {
132 return (param1.compareTo(param2) > 0) ? param1 : param2;
133 }
134 }
135
136 /**
137 * Binary minimum.
138 */
139 public static class Min<T extends Comparable<T>> implements ILambda.Binary<T, T, T> {
140 public T apply(T param1, T param2) {
141 return (param1.compareTo(param2) < 0) ? param1 : param2;
142 }
143 }
144 }
145
146 /**
147 * Ternary lambda interface R <- P x Q x S.
148 */
149 public static interface Ternary<R, P, Q, S> {
150 /**
151 * Apply the lambda.
152 * @param param1 lambda-specific first parameter
153 * @param param2 lambda-specific second parameter
154 * @param param3 lambda-specific third parameter
155 * @return lambda-specific return value
156 */
157 public abstract R apply(P param1, Q param2, S param3);
158
159 /**
160 * Binary decorator for a ternary lambda that binds a constant to its first parameter.
161 */
162 public static class Bind1st<R, P, Q, S> implements ILambda.Binary<R, Q, S> {
163 /**
164 * The constant first argument.
165 */
166 private P _constant;
167
168 /**
169 * The ternary lambda that is decorated.
170 */
171 private ILambda.Ternary<R, P, Q, S> _decoree;
172
173 /**
174 * Create a new binary decorator for a ternary lambda, binding a constant to its first parameter.
175 * @param decoree ternary lambda
176 * @param constant constant for the ternary lambda's first parameter
177 */
178 public Bind1st(Ternary<R, P, Q, S> decoree, P constant) {
179 _constant = constant;
180 _decoree = decoree;
181 }
182
183 /**
184 * Apply the binary decorator, i.e. apply the constant and the parameters to the ternary lambda.
185 * @param param2 argument for the ternary lambda's second parameter
186 * @param param3 argument for the ternary lambda's third parameter
187 * @return return value of the binary lambda
188 */
189 public R apply(Q param2, S param3) {
190 return _decoree.apply(_constant, param2, param3);
191 }
192 }
193
194 /**
195 * Binary decorator for a ternary lambda that binds a constant to its second parameter.
196 */
197 public static class Bind2nd<R, P, Q, S> implements ILambda.Binary<R, P, S> {
198 /**
199 * The constant second argument.
200 */
201 private Q _constant;
202
203 /**
204 * The ternary lambda that is decorated.
205 */
206 private ILambda.Ternary<R, P, Q, S> _decoree;
207
208 /**
209 * Create a new binary decorator for a ternary lambda, binding a constant to its second parameter.
210 * @param decoree ternary lambda
211 * @param constant constant for the ternary lambda's second parameter
212 */
213 public Bind2nd(Ternary<R, P, Q, S> decoree, Q constant) {
214 _constant = constant;
215 _decoree = decoree;
216 }
217
218 /**
219 * Apply the binary decorator, i.e. apply the constant and the parameters to the ternary lambda.
220 * @param param1 argument for the ternary lambda's first parameter
221 * @param param3 argument for the ternary lambda's third parameter
222 * @return return value of the binary lambda
223 */
224 public R apply(P param1, S param3) {
225 return _decoree.apply(param1, _constant, param3);
226 }
227 }
228
229 /**
230 * Binary decorator for a ternary lambda that binds a constant to its third parameter.
231 */
232 public static class Bind3rd<R, P, Q, S> implements ILambda.Binary<R, P, Q> {
233 /**
234 * The constant third argument.
235 */
236 private S _constant;
237
238 /**
239 * The ternary lambda that is decorated.
240 */
241 private ILambda.Ternary<R, P, Q, S> _decoree;
242
243 /**
244 * Create a new binary decorator for a ternary lambda, binding a constant to its third parameter.
245 * @param decoree ternary lambda
246 * @param constant constant for the ternary lambda's third parameter
247 */
248 public Bind3rd(Ternary<R, P, Q, S> decoree, S constant) {
249 _constant = constant;
250 _decoree = decoree;
251 }
252
253 /**
254 * Apply the binary decorator, i.e. apply the constant and the parameters to the ternary lambda.
255 * @param param1 argument for the ternary lambda's first parameter
256 * @param param2 argument for the ternary lambda's second parameter
257 * @return return value of the binary lambda
258 */
259 public R apply(P param1, Q param2) {
260 return _decoree.apply(param1, param2, _constant);
261 }
262 }
263
264 /**
265 * Unary decorator for a ternary lambda that binds constants to its first and second parameters.
266 */
267 public static class Bind1st2nd<R, P, Q, S> extends ILambda.Binary.Bind1st<R, P, S> {
268 /**
269 * Creates a new unary decorator for a ternary lambda, binding constants to its first and second parameter.
270 * @param decoree ternary lambda
271 * @param constant1 constant for the ternary lambda's first parameter
272 * @param constant2 constant for the ternary lambda's second parameter
273 */
274 public Bind1st2nd(Ternary<R, P, Q, S> decoree, P constant1, Q constant2) {
275 super(new Bind2nd<R, P, Q, S>(decoree, constant2), constant1);
276 }
277 }
278
279 /**
280 * Unary decorator for a ternary lambda that binds constants to its first and third parameters.
281 */
282 public static class Bind1st3rd<R, P, Q, S> extends ILambda.Binary.Bind1st<R, P, Q> {
283 /**
284 * Creates a new unary decorator for a ternary lambda, binding constants to its first and third parameter.
285 * @param decoree ternary lambda
286 * @param constant1 constant for the ternary lambda's first parameter
287 * @param constant3 constant for the ternary lambda's third parameter
288 */
289 public Bind1st3rd(Ternary<R, P, Q, S> decoree, P constant1, S constant3) {
290 super(new Bind3rd<R, P, Q, S>(decoree, constant3), constant1);
291 }
292 }
293
294 /**
295 * Unary decorator for a ternary lambda that binds constants to its second and third parameters.
296 */
297 public static class Bind2nd3rd<R, P, Q, S> extends ILambda.Binary.Bind2nd<R, P, Q> {
298 /**
299 * Creates a new unary decorator for a ternary lambda, binding constants to its second and third parameter.
300 * @param decoree ternary lambda
301 * @param constant2 constant for the ternary lambda's second parameter
302 * @param constant3 constant for the ternary lambda's third parameter
303 */
304 public Bind2nd3rd(Ternary<R, P, Q, S> decoree, Q constant2, S constant3) {
305 super(new Bind3rd<R, P, Q, S>(decoree, constant3), constant2);
306 }
307 }
308
309 /**
310 * Adapter to turn an N-ary lambda into a ternary lambda.
311 */
312 public static class NaryAdaptor<R, P> implements ILambda.Ternary<R, P, P, P> {
313 /**
314 * The N-ary lambda.
315 */
316 private ILambda.Nary<R, P> _decoree;
317
318 /**
319 * Creates a new ternary lambda.
320 * @param decoree N-ary lambda
321 */
322 public NaryAdaptor(ILambda.Nary<R, P> decoree) {
323 _decoree = decoree;
324 }
325
326 /**
327 * Apply the N-ary lambda.
328 * @param param1 the first parameter.
329 * @param param2 the second parameter.
330 * @param param3 the third parameter.
331 * @return return value of the N-ary lambda
332 */
333 public R apply(P param1, P param2, P param3) {
334 @SuppressWarnings("unchecked") R retval = _decoree.apply(param1, param2, param3);
335 return retval;
336 }
337 }
338
339 /**
340 * Ternary maximum.
341 */
342 public static class Max<T extends Comparable<T>> implements ILambda.Ternary<T, T, T, T> {
343 public T apply(T param1, T param2, T param3) {
344 T temp12 = (param1.compareTo(param2) > 0) ? param1 : param2;
345 return (temp12.compareTo(param3) > 0) ? temp12 : param3;
346 }
347 }
348
349 /**
350 * Ternary minimum.
351 */
352 public static class Min<T extends Comparable<T>> implements ILambda.Ternary<T, T, T, T> {
353 public T apply(T param1, T param2, T param3) {
354 T temp12 = (param1.compareTo(param2) < 0) ? param1 : param2;
355 return (temp12.compareTo(param3) < 0) ? temp12 : param3;
356 }
357 }
358 }
359
360 /**
361 * N-ary lambda interface R <- P x P x ... x P.
362 */
363 public static interface Nary<R, P> {
364 /**
365 * Apply the lambda.
366 * @param param lambda-specific parameters
367 * @return lambda-specific return value
368 */
369 public abstract R apply(P ... param);
370
371 /**
372 * Adapter to turn a unary lambda into an N-ary lambda (with N=1).
373 */
374 public static class UnaryAdaptor<R, P> implements Nary<R, P> {
375 /**
376 * The unary lambda.
377 */
378 private ILambda<R, P> _decoree;
379
380 /**
381 * Creates a new N-ary lambda (with N=1).
382 * @param decoree unary lambda
383 */
384 public UnaryAdaptor(ILambda<R, P> decoree) {
385 _decoree = decoree;
386 }
387
388 /**
389 * Apply the unary lambda.
390 * @param param exactly one parameter.
391 * @return return value of the unary lambda
392 * @throws IllegalArgumentException if param.length != 1
393 */
394 public R apply(P... param) {
395 if (param.length != 1) {
396 throw new IllegalArgumentException("UnaryAdapter.apply expects exactly one argument.");
397 }
398 return _decoree.apply(param[0]);
399 }
400 }
401
402 /**
403 * Adapter to turn a binary lambda into an N-ary lambda (with N=2).
404 */
405 public static class BinaryAdaptor<R, P> implements Nary<R, P> {
406 /**
407 * The binary lambda.
408 */
409 private ILambda.Binary<R, P, P> _decoree;
410
411 /**
412 * Creates a new N-ary lambda (with N=2).
413 * @param decoree binary lambda
414 */
415 public BinaryAdaptor(ILambda.Binary<R, P, P> decoree) {
416 _decoree = decoree;
417 }
418
419 /**
420 * Apply the binary lambda.
421 * @param param exactly two parameter.
422 * @return return value of the binary lambda
423 * @throws IllegalArgumentException if param.length != 2
424 */
425 public R apply(P... param) {
426 if (param.length != 2) {
427 throw new IllegalArgumentException("BinaryAdapter.apply expects exactly two arguments.");
428 }
429 return _decoree.apply(param[0], param[1]);
430 }
431 }
432
433 /**
434 * Adapter to turn a ternary lambda into an N-ary lambda (with N=3).
435 */
436 public static class TernaryAdaptor<R, P> implements Nary<R, P> {
437 /**
438 * The ternary lambda.
439 */
440 private ILambda.Ternary<R, P, P, P> _decoree;
441
442 /**
443 * Creates a new N-ary lambda (with N=3).
444 * @param decoree ternarylambda
445 */
446 public TernaryAdaptor(ILambda.Ternary<R, P, P, P> decoree) {
447 _decoree = decoree;
448 }
449
450 /**
451 * Apply the ternary lambda.
452 * @param param exactly three parameter.
453 * @return return value of the ternary lambda
454 * @throws IllegalArgumentException if param.length != 3
455 */
456 public R apply(P... param) {
457 if (param.length != 3) {
458 throw new IllegalArgumentException("TernaryAdapter.apply expects exactly three arguments.");
459 }
460 return _decoree.apply(param[0], param[1], param[2]);
461 }
462 }
463
464 /**
465 * (N-1)-ary decorator for an N-ary lambda that binds a constant to one of its parameters.
466 */
467 public static class Bind<R, P> implements Nary<R, P> {
468 /**
469 * The index of the constant parameter.
470 */
471 private int _index;
472
473 /**
474 * The constant argument.
475 */
476 private P _constant;
477
478 /**
479 * The N-ary lambda.
480 */
481 private ILambda.Nary<R, P> _decoree;
482
483 /**
484 * Creates a new (N-1)-ary decorator for an N-ary lambda, binding a constant to one of its parameters.
485 * @param decoree N-ary lambda
486 * @param index index of the constant parameter, 0 <= index < N
487 * @param constant constant for the specified parameter
488 */
489 public Bind(Nary<R, P> decoree, int index, P constant) {
490 _index = index;
491 _constant = constant;
492 _decoree = decoree;
493 }
494
495 /**
496 * Apply the (N-1)-ary decorator, i.e. apply the N-ary lambda with the constant spliced into the given
497 * (N-1) arguments.
498 * @param param (N-1) arguments
499 * @return return value of the N-ary lambda
500 */
501 public R apply(P... param) {
502 LinkedList<P> ps = new LinkedList<P>(Arrays.asList(param));
503 ps.add(_index, _constant);
504 return _decoree.apply(ps.toArray(param));
505 }
506 }
507
508 /**
509 * (N-K)-ary decorator for an N-ary lambda that binds constants to K of its parameters.
510 */
511 public static class BindK<R, P> implements Nary<R, P> {
512 /**
513 * Array with indices of the constant parameters.
514 */
515 private int[] _indices;
516
517 /**
518 * Array with constant arguments.
519 */
520 private P[] _constants;
521
522 /**
523 * The N-ary lambda.
524 */
525 private Nary<R, P> _decoree;
526
527 /**
528 * Creates a new (N-K)-ary decorator for an N-ary lambda, binding constants to K of its parameters.
529 * @param decoree N-ary lambda
530 * @param indices array of K indices in strictly ascending order, each 0 <= index < N
531 * @param constants K constant arguments
532 * @throws IllegalArgumentException if indices.length != constants.length
533 */
534 public BindK(Nary<R, P> decoree, int[] indices, P... constants) {
535 if (indices.length != constants.length) {
536 throw new IllegalArgumentException("Indices and constants arrays need to be the same length.");
537 }
538 _indices = indices;
539 _constants = constants;
540 _decoree = decoree;
541 }
542
543 /**
544 * Apply the (N-K)-ary decorator, i.e. apply the N-ary lambda with the K constants spliced into the given
545 * (N-K) arguments.
546 * @param param (N-K) arguments
547 * @return return value of the N-ary lambda
548 */
549 public R apply(P... param) {
550 LinkedList<P> ps = new LinkedList<P>(Arrays.asList(param));
551 for(int i = 0; i < _indices.length; ++i) {
552 ps.add(_indices[i], _constants[i]);
553 }
554 return _decoree.apply(ps.toArray(param));
555 }
556 }
557
558 /**
559 * N-ary maximum.
560 */
561 public static class Max<T extends Comparable<T>> implements ILambda.Nary<T, T> {
562 public T apply(T ... param) {
563 if (param.length==0) {
564 throw new IllegalArgumentException("N-ary Max needs at least one argument.");
565 }
566 T accum = param[0];
567 for (int i=1; i<param.length; ++i) {
568 if (param[i].compareTo(accum) > 0) { accum = param[i]; }
569 }
570 return accum;
571 }
572 }
573
574 /**
575 * N-ary minimum.
576 */
577 public static class Min<T extends Comparable<T>> implements ILambda.Nary<T, T> {
578 public T apply(T ... param) {
579 if (param.length==0) {
580 throw new IllegalArgumentException("N-ary Min needs at least one argument.");
581 }
582 T accum = param[0];
583 for (int i=1; i<param.length; ++i) {
584 if (param[i].compareTo(accum) < 0) { accum = param[i]; }
585 }
586 return accum;
587 }
588 }
589 }
590
591 /**
592 * Adapter to turn an N-ary lambda into a unary lambda.
593 */
594 public static class NaryAdaptor<R, P> implements ILambda<R, P> {
595 /**
596 * The N-ary lambda.
597 */
598 private ILambda.Nary<R, P> _decoree;
599
600 /**
601 * Creates a new unary lambda.
602 * @param decoree N-ary lambda
603 */
604 public NaryAdaptor(ILambda.Nary<R, P> decoree) {
605 _decoree = decoree;
606 }
607
608 /**
609 * Apply the N-ary lambda.
610 * @param param the parameter.
611 * @return return value of the N-ary lambda
612 */
613 public R apply(P param) {
614 @SuppressWarnings("unchecked") R retval = _decoree.apply(param);
615 return retval;
616 }
617 }
618 }