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 }