aa
TestHM1.java
Go to the documentation of this file.
1 package com.cliffc.aa.HM;
2 
3 import com.cliffc.aa.type.*;
4 import org.junit.Before;
5 import org.junit.Test;
6 
7 import static com.cliffc.aa.HM.HM1.*;
8 import static org.junit.Assert.assertEquals;
9 
10 public class TestHM1 {
11 
12  @Before public void reset() { HM1.reset(); }
13 
14  @Test(expected = RuntimeException.class)
15  public void test0() {
16  Syntax syn = new Ident("fred");
17  HM1.HM(syn);
18  }
19 
20  @Test
21  public void test1() {
22  Syntax syn = new Con(TypeInt.con(3));
23  HMVar t = (HMVar)HM1.HM(syn);
24  assertEquals(TypeInt.con(3),t.type());
25  }
26 
27  @Test
28  public void test2() {
29  Syntax syn = new Apply(new Ident("pair"),new Con(TypeInt.con(3)));
30  HMType t = HM1.HM(syn);
31  assertEquals("{ v9 -> pair(v8:3,v9$) }",t.str());
32  }
33 
34  @Test
35  public void test3() {
36  // { x -> (pair (x 3) (x "abc")) }
37  Syntax x =
38  new Lambda("x",
39  new Apply(new Apply(new Ident("pair"),
40  new Apply(new Ident("x"), new Con(TypeInt.con(3)))),
41  new Apply(new Ident("x"), new Con(TypeStr.ABC))));
42  HMType t1 = HM1.HM(x);
43  assertEquals("{ { v11:all -> v9 } -> pair(v9$,v9$) }",t1.str());
44  }
45 
46  @Test
47  public void test4() {
48  // let fact = {n -> ( if/else (==0 n) 1 ( * n (fact (dec n))))} in fact;
49  // let fact = {n -> (((if/else (==0 n)) 1) ((* n) (fact (dec n))))} in fact;
50  Syntax fact =
51  new Let("fact",
52  new Lambda("n",
53  new Apply(new Apply( new Apply(new Ident("if/else"),
54  new Apply(new Ident("==0"),new Ident("n"))),
55  new Con(TypeInt.con(1))),
56  new Apply(new Apply(new Ident("*"), new Ident("n")),
57  new Apply(new Ident("fact"),
58  new Apply(new Ident("dec"),new Ident("n")))))),
59  new Ident("fact"));
60  HMType t1 = HM1.HM(fact);
61  assertEquals("{ v25:int64 -> v25$ }",t1.str());
62  }
63 
64  @Test
65  public void test5() {
66  // ({ x -> (pair (x 3) (x "abc")) } {y->y})
67  Syntax x =
68  new Apply(new Lambda("x",
69  new Apply(new Apply(new Ident("pair"),
70  new Apply(new Ident("x"), new Con(TypeInt.con(3)))),
71  new Apply(new Ident("x"), new Con(TypeStr.ABC)))),
72  new Lambda("y", new Ident("y")));
73 
74  HMType t1 = HM1.HM(x);
75  assertEquals("pair(v17:all,v17$)",t1.str());
76  }
77 
78  @Test(expected = RuntimeException.class)
79  public void test6() {
80  // recursive unification
81  // fn f => f f (fail)
82  Syntax x =
83  new Lambda("f", new Apply(new Ident("f"), new Ident("f")));
84  HMType t1 = HM1.HM(x);
85  assertEquals("TBD",t1.str());
86  }
87 
88  @Test
89  public void test7() {
90  // let g = fn f => 5 in g g
91  Syntax x =
92  new Let("g",
93  new Lambda("f", new Con(TypeInt.con(5))),
94  new Apply(new Ident("g"), new Ident("g")));
95  HMType t1 = HM1.HM(x);
96  assertEquals("v12:5",t1.str());
97  }
98 
99  @Test
100  public void test8() {
101  // example that demonstrates generic and non-generic variables:
102  // fn g => let f = (fn x => g) in pair (f 3, f true)
103  Syntax syn =
104  new Lambda("g",
105  new Let("f",
106  new Lambda("x", new Ident("g")),
107  new Apply(
108  new Apply(new Ident("pair"),
109  new Apply(new Ident("f"), new Con(TypeInt.con(3)))
110  ),
111  new Apply(new Ident("f"), new Con(TypeInt.con(1))))));
112  HMType t1 = HM1.HM(syn);
113  assertEquals("{ v11 -> pair(v11$,v11$) }",t1.str());
114  }
115 
116  @Test
117  public void test10() {
118  // Function composition
119  // fn f (fn g (fn arg (f g arg)))
120  Syntax syn =
121  new Lambda("f", new Lambda("g", new Lambda("arg", new Apply(new Ident("g"), new Apply(new Ident("f"), new Ident("arg"))))));
122 
123  HMType t1 = HM1.HM(syn);
124  assertEquals("{ { v10 -> v11 } -> { { v11$ -> v12 } -> { v10$ -> v12$ } } }",t1.str());
125  }
126 
127  @Test
128  public void test13() {
129  // Looking at when tvars are duplicated ("fresh" copies made).
130  // This is the "map" problem with a scalar instead of a collection.
131  // Takes a '{a->b}' and a 'a' for a couple of different prims.
132  // let map = { fun -> {x -> (fun x) }} in ((pair ((map str) 5)) ((map factor) 2.3))
133  Syntax syn =
134  new Let("map",
135  new Lambda("fun",
136  new Lambda("x",
137  new Apply(new Ident("fun"),new Ident("x")))),
138  new Apply(new Apply(new Ident("pair"),
139  new Apply(new Apply(new Ident("map"),
140  new Ident("str")), new Con(TypeInt.con(5)))),
141  new Apply(new Apply(new Ident("map"),
142  // "factor" a float returns a pair (mod,rem).
143  new Ident("factor")), new Con(TypeFlt.con(2.3)))));
144  HMType t1 = HM1.HM(syn);
145  assertEquals("pair(v12:*str,pair(v26:flt64,v26$))",t1.str());
146  }
147 
148  @Test(expected = RuntimeException.class)
149  public void test17() {
150  // Checking behavior when using "if/else" to merge two functions with
151  // sufficiently different signatures, then attempting to pass them to a map
152  // & calling internally.
153  // fcn takes a predicate 'p' and returns one of two fcns.
154  // let fcn = { p -> (((if/else p) {a -> pair[a,a]}) {b -> pair[b,pair[3,b]]}) } in
155  // map takes a function and an element (collection?) and applies it (applies to collection?)
156  // let map = { fun -> {x -> (fun x) }} in
157  // { q -> ((map (fcn q)) 5) }
158  // Should return either { p -> p ? [5,5] : [5,[3,5]] }
159  Syntax syn =
160  new Let("fcn",
161  new Lambda("p",
162  new Apply(new Apply(new Apply(new Ident("if/else"),new Ident("p")), // p ?
163  new Lambda("a",
164  new Apply(new Apply(new Ident("pair"),new Ident("a")),
165  new Ident("a")))),
166  new Lambda("b",
167  new Apply(new Apply(new Ident("pair"),new Ident("b")),
168  new Apply(new Apply(new Ident("pair"),new Con(TypeInt.con(3))),
169  new Ident("b")))))),
170  new Let("map",
171  new Lambda("fun",
172  new Lambda("x",
173  new Apply(new Ident("fun"),new Ident("x")))),
174  new Lambda("q",
175  new Apply(new Apply(new Ident("map"),
176  new Apply(new Ident("fcn"),new Ident("q"))),
177  new Con(TypeInt.con(5))))));
178  // Ultimately, unifies "a" with "pair[3,a]" which throws recursive unification.
179  HMType t1 = HM1.HM(syn);
180  assertEquals("TBD",t1.str());
181  }
182 
183  @Test
184  public void test18() {
185  // Hand-rolled cons/cdr
186  // let cons = { x y -> { cadr -> (cadr x y) } }
187  // in let cdr = { mycons -> (mycons { p q -> q}) }
188  // in (cdr (cons 2 3))
189  Syntax syn =
190  new Let("cons", new Lambda2("x","y",
191  new Lambda("cadr",new Apply(new Ident("cadr"),new Ident("x"),new Ident("y")))),
192  new Let("cdr", new Lambda("mycons", new Apply(new Ident("mycons"), new Lambda2("p","q", new Ident("q")))),
193  new Apply(new Ident("cdr"),
194  new Apply(new Ident("cons"), new Con(TypeInt.con(2)), new Con(TypeInt.con(3))))));
195  HMType t1 = HM1.HM(syn);
196  assertEquals("v20:3",t1.str());
197  }
198 
199  @Test
200  public void test20() {
201  // let f0 = fn f x => (if/else3 (==0 x) 1 (f (f0 f (dec x)) 2) ) in f0 *2 99
202  Syntax syn =
203  new Let("f0", new Lambda2("f","x",
204  new Apply(new Ident("if/else3"),
205  new Apply(new Ident("==0"), new Ident("x")),
206  new Con(TypeInt.con(1)),
207  new Apply(new Ident("f"),
208  new Apply(new Ident("f0"),
209  new Ident("f"),
210  new Apply(new Ident("dec"), new Ident("x"))),
211  new Con(TypeInt.con(2)))
212  )
213  ),
214  new Apply(new Ident("f0"), new Ident("*2"), new Con(TypeInt.con(99))));
215  HMType t1 = HM1.HM(syn);
216  assertEquals("v24:int64",t1.str());
217  }
218 
219  // Toss a function into a pair & pull it back out
220  @Test
221  public void test23() {
222  // { g ->
223  // let fgz =
224  // // Hand-rolled cons/cdr
225  // let cons = { x y -> { cadr -> (cadr x y) } }
226  // in let cdr = { mycons -> (mycons { p q -> q}) }
227  // in (cdr (cons 2 {z -> g z}))
228  // in ((pair (fgz 3)) (fgz 5))
229  // }
230  Syntax syn =
231  new Lambda("g",
232  new Let("fgz",
233  new Let("cons",
234  new Lambda2("x","y", new Lambda("cadr",new Apply(new Ident("cadr"),new Ident("x"),new Ident("y")))),
235  new Let("cdr",
236  new Lambda("mycons", new Apply(new Ident("mycons"), new Lambda2("p","q", new Ident("q")))),
237  new Apply(new Ident("cdr"),
238  new Apply(new Ident("cons"),
239  new Con(TypeInt.con(2)),
240  new Lambda("z",new Apply(new Ident("g"),new Ident("z"))))))),
241  new Apply(new Apply(new Ident("pair"),
242  new Apply(new Ident("fgz"),new Con(TypeInt.con(3)))),
243  new Apply(new Ident("fgz"),new Con(TypeInt.con(5))))));
244  HMType t1 = HM1.HM(syn);
245  assertEquals("{ { v27:nint8 -> v31 } -> pair(v31$,v31$) }",t1.str());
246  }
247 
248 }
com.cliffc.aa.HM.HM1.HM
static HMType HM(Syntax prog)
Definition: HM1.java:24
com.cliffc.aa.HM.TestHM1.test13
void test13()
Definition: TestHM1.java:128
com.cliffc.aa.HM.TestHM1.reset
void reset()
Definition: TestHM1.java:12
com.cliffc
com.cliffc.aa.HM.TestHM1.test1
void test1()
Definition: TestHM1.java:21
com.cliffc.aa.type.TypeInt
Definition: TypeInt.java:9
com.cliffc.aa.HM.TestHM1.test23
void test23()
Definition: TestHM1.java:221
com.cliffc.aa.type.TypeFlt
Definition: TypeFlt.java:9
com.cliffc.aa.type.TypeInt.con
static TypeInt con(long con)
Definition: TypeInt.java:37
com.cliffc.aa.HM.TestHM1.test7
void test7()
Definition: TestHM1.java:89
com.cliffc.aa.HM.TestHM1.test10
void test10()
Definition: TestHM1.java:117
com.cliffc.aa.HM.TestHM1.test8
void test8()
Definition: TestHM1.java:100
Test
com.cliffc.aa.HM.TestHM1
Definition: TestHM1.java:10
com.cliffc.aa.HM.TestHM1.test4
void test4()
Definition: TestHM1.java:47
com.cliffc.aa.HM.TestHM1.test2
void test2()
Definition: TestHM1.java:28
com.cliffc.aa.type.TypeFlt.con
static Type con(double con)
Definition: TypeFlt.java:36
com.cliffc.aa.HM.TestHM1.test5
void test5()
Definition: TestHM1.java:65
com.cliffc.aa.HM.HM1
Hindley-Milner typing.
Definition: HM1.java:23
com.cliffc.aa.type.TypeStr.ABC
static final TypeStr ABC
Definition: TypeStr.java:47
com.cliffc.aa.HM.TestHM1.test0
void test0()
Definition: TestHM1.java:15
com.cliffc.aa.type.TypeStr
Definition: TypeStr.java:14
com.cliffc.aa.HM.TestHM1.test3
void test3()
Definition: TestHM1.java:35
com.cliffc.aa.HM.TestHM1.test18
void test18()
Definition: TestHM1.java:184
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.HM.TestHM1.test6
void test6()
Definition: TestHM1.java:79
com.cliffc.aa.HM.HM1.reset
static void reset()
Definition: HM1.java:53
com.cliffc.aa.HM
Definition: HM.java:1
com.cliffc.aa.HM.TestHM1.test20
void test20()
Definition: TestHM1.java:200
com
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.HM.TestHM1.test17
void test17()
Definition: TestHM1.java:149