import edu.rice.cs.mint.runtime.Code;

import java.util.*;

public class GenericsTest {
//    public static abstract class GenMethod {
//        public separable abstract <Y> Code<Y> fun(Code<Y> c1, Code<Y> c2, Class<Y> cy);
//    }
//
//    public static abstract class GenMethod2 {
//        public separable abstract <Y,X extends Integer> Code<Y> fun(Code<Y> c1, Code<Y> c2, Class<Y> cy,
//                                                                    X x, Class<X> cx);
//    }
//
//    public static abstract class GenMethod3 {
//        public separable abstract <Y> Code<Y[]> fun(Code<Y> c1, Code<Y> c2, Class<Y> cy);
//    }
//
//    public static abstract class GenMethod4 {
//        public separable abstract <Y> Code<ArrayList<Y>> fun(Code<Y> c1, Code<Y> c2, Class<Y> cy);
//    }
//    
//    
//    
//    
//    public static abstract class GenClass<Y> {
//        public separable abstract Code<Y> fun(Code<Y> c1, Code<Y> c2, Class<Y> cy);
//    }
//
//    public static abstract class GenClass2<Y,X extends Integer>  {
//        public separable abstract Code<Y> fun(Code<Y> c1, Code<Y> c2, Class<Y> cy,
//                                                                    X x, Class<X> cx);
//    }
//
//    public static abstract class GenClass3<Y> {
//        public separable abstract Code<Y[]> fun(Code<Y> c1, Code<Y> c2, Class<Y> cy);
//    }
//
//    public static abstract class GenClass4<Y> {
//        public separable abstract Code<ArrayList<Y>> fun(Code<Y> c1, Code<Y> c2, Class<Y> cy);
//    }
//
//    
//    public static class GenClassWrapperMethod {
//        public static <X> void foo(Code<X> c1, Code<X> c2, Class<X> cx) {
//            System.out.println(new GenClass<X>() {
//                public separable Code<X> fun(Code<X> c1, Code<X> c2, final Class<X> cy) {
//                    return <| /* gratuitous cast to Y */ (X) ( true ? `c1 : `c2 ) |>;
//                }
//            }.fun(c1, c2, cx).run());
//        }
//    }
//    
//    public static class GenClassWrapperClass<Z> {
//        public void foo(Code<Z> c1, Code<Z> c2, Class<Z> cz) {
//            System.out.println(new GenClass<Z>() {
//                public separable Code<Z> fun(Code<Z> c1, Code<Z> c2, final Class<Z> cy) {
//                    return <| /* gratuitous cast to Z */ (Z) ( true ? `c1 : `c2 ) |>;
//                }
//            }.fun(c1, c2, cz).run());
//        }
//    }
//
//    public static class GenClassWrapperClass2<Z> {
//        public abstract class GenMethod0 {
//            public separable abstract Code<Z> fun(Code<Z> c1, Code<Z> c2);
//        }       
//        public void foo(Code<Z> c1, Code<Z> c2, final Class<Z> cz) {
//            System.out.println(new GenMethod0() {
//                public separable Code<Z> fun(Code<Z> c1, Code<Z> c2) {
//                    return <| /* gratuitous cast to Z */ (Z) ( true ? `c1 : `c2 ) |>;
//                }
//            }.fun(c1, c2).run());
//        }
//    }

    public static class GenClassWrapperClass3<Z> {
        public final Class<Z> cz;
        public GenClassWrapperClass3(Class<Z> cz) { this.cz = cz; }
        public abstract class GenMethod0 {
            public separable abstract Code<Z> fun(Code<Z> c1, Code<Z> c2);
        }
        public void foo(Code<Z> foo1, Code<Z> foo2) {
            System.out.println(new GenMethod0() {
                public separable Code<Z> fun(Code<Z> c1, Code<Z> c2) {
//                    final Class<Z> czz = cz;
                    return <| /* gratuitous cast to Z */ (Z) ( true ? `c1 : `c2 ) |>;
                }
            }.fun(foo1, foo2).run());
        }
    }
    
    public static void main(String[] args) {
//        System.out.println(new GenMethod() {
//            public separable <Y> Code<Y> fun(Code<Y> c1, Code<Y> c2, final Class<Y> cy) {
//                return <| /* gratuitous cast to Y */ (Y) ( true ? `c1 : `c2 ) |>;
//            }
//        }.fun(<| 1 |>, <| 2 |>, Integer.class).run());
//
//        System.out.println(new GenMethod2() {
//            public separable <Y,X extends Integer> Code<Y> fun(Code<Y> c1, Code<Y> c2, final Class<Y> cy,
//                                                               final X x, final Class<X> cx) {
//                return <|
//                    ((`(edu.rice.cs.mint.util.Lift.lift(x)))</* gratuitious cast to X */ (X)new Integer(0))
//                    ? (/* gratuitous cast to Y */ (Y) ( true  ? `c1 : `c2 )) 
//                    : (/* gratuitous cast to Y */ (Y) ( false ? `c1 : `c2 )) |>;
//            }
//        }.fun(<| 1 |>, <| 2 |>, Integer.class, 5, Integer.class).run());
//
//        System.out.println(new GenMethod3() {
//            public separable <Y> Code<Y[]> fun(Code<Y> c1, Code<Y> c2, final Class<Y> cy) {
//                return <| /* gratuitous cast to Y */ (Y[]) ( null ) |>;
//            }
//        }.fun(<| 1 |>, <| 2 |>, Integer.class).run());
//
//        System.out.println(new GenMethod4() {
//            public separable <Y> Code<ArrayList<Y>> fun(Code<Y> c1, Code<Y> c2, final Class<Y> cy) {
//                return <| /* gratuitous cast to Y */ (ArrayList<Y>) ( new ArrayList<Y>() ) |>;
//            }
//        }.fun(<| 1 |>, <| 2 |>, Integer.class).run());
//        
//        
//        GenClassWrapperMethod.foo(<| 1 |>, <| 2 |>, Integer.class);
//        new GenClassWrapperClass<Integer>().foo(<| 1 |>, <| 2 |>, Integer.class);
//        new GenClassWrapperClass2<Integer>().foo(<| 1 |>, <| 2 |>, Integer.class);
        new GenClassWrapperClass3<Integer>(Integer.class).foo(<| 1 |>, <| 2 |>);
    }
}
