aa
TestHM4.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.HM4.*;
8 import static org.junit.Assert.assertEquals;
9 
10 public class TestHM4 {
11 
12  @Before public void reset() { HM4.reset(); }
13 
14  @Test(expected = RuntimeException.class)
15  public void test00() {
16  Syntax syn = new Ident("fred");
17  HM4.hm(syn);
18  }
19 
20  @Test
21  public void test01() {
22  Syntax syn = new Con(TypeInt.con(3));
23  T2 t = HM4.hm(syn);
24  assertEquals("3",t.p());
25  }
26 
27  @Test
28  public void test02() {
29  Syntax syn = new Apply(new Ident("pair"),new Con(TypeInt.con(3)));
30  T2 t = HM4.hm(syn);
31  assertEquals("{ V36 -> (pair 3 V36) }",t.p());
32  }
33 
34  @Test
35  public void test03() {
36  // { z -> (pair2 (z 3) (z "abc")) }
37  Syntax x =
38  new Lambda("z",
39  new Apply(new Ident("pair2"),
40  new Apply(new Ident("z"), new Con(TypeInt.con(3))),
41  new Apply(new Ident("z"), new Con(TypeStr.ABC))));
42  T2 t = HM4.hm(x);
43  assertEquals("{ { all -> V34 } -> (pair2 V34 V34) }",t.p());
44  }
45 
46  @Test
47  public void test04() {
48  // let fact = {n -> (if/else3 (==0 n) 1 (*2 n (fact (dec n))))} in fact;
49  Syntax fact =
50  new Let("fact",
51  new Lambda("n",
52  new Apply(new Ident("if/else3"),
53  new Apply(new Ident("==0"),new Ident("n")), // Predicate
54  new Con(TypeInt.con(1)), // True arm
55  new Apply(new Ident("*2"), // False arm
56  new Ident("n"),
57  new Apply(new Ident("fact"),
58  new Apply(new Ident("dec"),new Ident("n")))))),
59  new Ident("fact"));
60  T2 t = HM4.hm(fact);
61  assertEquals("#{ int64 -> int64 }",t.p());
62  }
63 
64  @Test
65  public void test05() {
66  // ({ x -> (pair2 (x 3) (x "abc")) } {y->y})
67  // Because {y->y} is passed in, all 'y' types must agree.
68  // This unifies 3 and "abc" which results in 'all'
69  Syntax x =
70  new Apply(new Lambda("x",
71  new Apply(new Ident("pair2"),
72  new Apply(new Ident("x"), new Con(TypeInt.con(3))),
73  new Apply(new Ident("x"), new Con(TypeStr.ABC)))),
74  new Lambda("y", new Ident("y")));
75 
76  T2 t1 = HM4.hm(x);
77  assertEquals("(pair2 all all)",t1.p());
78  }
79 
80  @Test//(expected = RuntimeException.class) No longer throws, but returns a recursive type
81  public void test06() {
82  // recursive unification
83  // fn f => f f (fail)
84  Syntax x =
85  new Lambda("f", new Apply(new Ident("f"), new Ident("f")));
86  T2 t1 = HM4.hm(x);
87  assertEquals("{ $36:{ $36 -> V33 } -> V33 }",t1.p());
88  // We can argue the pretty-print should print:
89  // "$36:{ $36 -> V33 }"
90  }
91 
92  @Test
93  public void test07() {
94  // let g = fn f => 5 in g g
95  Syntax x =
96  new Let("g",
97  new Lambda("f", new Con(TypeInt.con(5))),
98  new Apply(new Ident("g"), new Ident("g")));
99  T2 t1 = HM4.hm(x);
100  assertEquals("5",t1.p());
101  }
102 
103  @Test
104  public void test08() {
105  // example that demonstrates generic and non-generic variables:
106  // fn g => let f = (fn x => g) in pair2 (f 3, f true)
107  Syntax syn =
108  new Lambda("g",
109  new Let("f",
110  new Lambda("x", new Ident("g")),
111  new Apply(new Ident("pair2"),
112  new Apply(new Ident("f"), new Con(TypeInt.con(3))),
113  new Apply(new Ident("f"), new Con(TypeInt.con(1))))));
114  T2 t1 = HM4.hm(syn);
115  assertEquals("{ V2 -> (pair2 V2 V2) }",t1.p());
116  }
117 
118  @Test
119  public void test09() {
120  // fn f g => (f g)
121  Syntax syn =
122  new Lambda2("f", "g", new Apply(new Ident("f"), new Ident("g")));
123  T2 t1 = HM4.hm(syn);
124  assertEquals("{ { V1 -> V34 } V1 -> V34 }",t1.p());
125  }
126 
127  @Test
128  public void test10() {
129  // Function composition
130  // fn f g => (fn arg => g (f arg))
131  Syntax syn =
132  new Lambda2("f", "g", new Lambda("arg", new Apply(new Ident("g"), new Apply(new Ident("f"), new Ident("arg")))));
133  T2 t1 = HM4.hm(syn);
134  assertEquals("{ { V0 -> V37 } { V37 -> V36 } -> { V0 -> V36 } }",t1.p());
135  }
136 
137  @Test
138  public void test11() {
139  // Stacked functions ignoring all function arguments
140  // let map = (fn fun => (fn x => 2))
141  // in ((map 3) 5)
142  Syntax syn =
143  new Let("map",
144  new Lambda("fun",
145  new Lambda("x",
146  new Con(TypeInt.con(2)))),
147  new Apply(new Apply(new Ident("map"),
148  new Con(TypeInt.con(3))),
149  new Con(TypeInt.con(5))));
150  T2 t1 = HM4.hm(syn);
151  assertEquals("2",t1.p());
152  }
153 
154  @Test
155  public void test12() {
156  // map takes a function and an element (collection?) and applies it (applies to collection?)
157  // let map = { fun -> {x -> (fun x) }}
158  // in { p -> 5 }
159  Syntax syn =
160  new Let("map",
161  new Lambda("fun",
162  new Lambda("x",
163  new Apply(new Ident("fun"),new Ident("x")))),
164  new Lambda("p",
165  new Con(TypeInt.con(5))));
166  T2 t1 = HM4.hm(syn);
167  assertEquals("{ V2 -> 5 }",t1.p());
168  }
169 
170  @Test
171  public void test13() {
172  // Looking at when tvars are duplicated ("fresh" copies made).
173  // This is the "map" problem with a scalar instead of a collection.
174  // Takes a '{a->b}' and a 'a' for a couple of different prims.
175  // let map = { fun -> {x -> (fun x) }}
176  // in (pair2 ((map str) 5) ((map factor) 2.3))
177  Syntax syn =
178  new Let("map",
179  new Lambda("fun",
180  new Lambda("x",
181  new Apply(new Ident("fun"),new Ident("x")))),
182  new Apply(new Ident("pair2"),
183  new Apply(new Apply(new Ident("map"), new Ident("str")),
184  new Con(TypeInt.con(5))),
185  new Apply(new Apply(new Ident("map"), new Ident("factor")),
186  new Con(TypeFlt.con(2.3))))
187  );
188  T2 t1 = HM4.hm(syn);
189  assertEquals("(pair2 str (divmod flt64 flt64))",t1.p());
190  }
191 
192  @Test
193  public void test14() {
194  // map takes a function and an element (collection?) and applies it (applies to collection?)
195  // let map = { fun -> {x -> (fun x) }}
196  // in (map {a -> 3} 5)
197  Syntax syn =
198  new Let("map",
199  new Lambda("fun",
200  new Lambda("x",
201  new Apply(new Ident("fun"),new Ident("x")))),
202  new Apply(new Apply(new Ident("map"),
203  new Lambda("a",new Con(TypeInt.con(3)))),
204  new Con(TypeInt.con(5))));
205  T2 t1 = HM4.hm(syn);
206  assertEquals("3",t1.p());
207  }
208 
209  @Test
210  public void test15() {
211  // map takes a function and an element (collection?) and applies it (applies to collection?)
212  // let map = { fun -> {x -> (fun x) }}
213  // in (map {a -> [a,a]} 5)
214  Syntax syn =
215  new Let("map",
216  new Lambda("fun",
217  new Lambda("x",
218  new Apply(new Ident("fun"),new Ident("x")))),
219  new Apply(new Apply(new Ident("map"),
220  new Lambda("a",
221  new Apply(new Ident("pair2"),
222  new Ident("a"),
223  new Ident("a")))),
224  new Con(TypeInt.con(5))));
225  T2 t1 = HM4.hm(syn);
226  assertEquals("(pair2 5 5)",t1.p());
227  }
228 
229  @Test
230  public void test16() {
231  // let fcn = { p a -> pair[a,a] } in
232  // map takes a function and an element (collection?) and applies it (applies to collection?)
233  // let map = { fun x -> (fun x) } in
234  // in { q -> (map (fcn q) 5) }
235  // Should return { p -> [5,5] }
236  Syntax syn =
237  new Let("fcn",
238  new Lambda("p",
239  new Lambda("a",
240  new Apply(new Ident("pair2"),
241  new Ident("a"),
242  new Ident("a")))),
243  new Let("map",
244  new Lambda2("fun", "x", new Apply(new Ident("fun"),new Ident("x"))),
245  new Lambda("q",
246  new Apply(new Ident("map"),
247  new Apply(new Ident("fcn"),new Ident("q")),
248  new Con(TypeInt.con(5))))));
249  T2 t1 = HM4.hm(syn);
250  assertEquals("{ V4 -> (pair2 5 5) }",t1.p());
251  }
252 
253  @Test(expected = RuntimeException.class)
254  public void test17() {
255  // Checking behavior when using "if/else" to merge two functions with
256  // sufficiently different signatures, then attempting to pass them to a map
257  // & calling internally.
258  // fcn takes a predicate 'p' and returns one of two fcns.
259  // let fcn = { p -> (if/else3 p {a -> pair[a,a ]}
260  // {b -> pair[b,pair[3,b]]}) } in
261  // map takes a function and an element (collection?) and applies it (applies to collection?)
262  // let map = { fun x -> (fun x) }
263  // in { q -> ((map (fcn q)) 5) }
264  // Should return { q -> q ? [5,5] : [5,[3,5]] }
265  Syntax syn =
266  new Let("fcn",
267  new Lambda("p",
268  new Apply(new Ident("if/else3"),
269  new Ident("p"), // p ?
270  new Lambda("a",
271  new Apply(new Ident("pair2"),
272  new Ident("a"),
273  new Ident("a"))),
274  new Lambda("b",
275  new Apply(new Ident("pair2"),
276  new Ident("b"),
277  new Apply(new Ident("pair2"),
278  new Con(TypeInt.con(3)),
279  new Ident("b")))))),
280  new Let("map",
281  new Lambda2("fun","x",new Apply(new Ident("fun"),new Ident("x"))),
282  new Lambda("q",
283  new Apply(new Ident("map"),
284  new Apply(new Ident("fcn"),new Ident("q")),
285  new Con(TypeInt.con(5))))));
286  // Ultimately, unifies "a" with "pair[3,a]" which throws recursive unification.
287  T2 t1 = HM4.hm(syn);
288  assertEquals("TBD",t1.p());
289  }
290 
291  @Test
292  public void test18() {
293  // Hand-rolled cons/cdr
294  // let cons = { x y -> { cadr -> (cadr x y) } }
295  // in let cdr = { mycons -> (mycons { p q -> q}) }
296  // in (cdr (cons 2 3))
297  Syntax syn =
298  new Let("cons", new Lambda2("x","y",
299  new Lambda("cadr",new Apply(new Ident("cadr"),new Ident("x"),new Ident("y")))),
300  new Let("cdr", new Lambda("mycons", new Apply(new Ident("mycons"), new Lambda2("p","q", new Ident("q")))),
301  new Apply(new Ident("cdr"),
302  new Apply(new Ident("cons"), new Con(TypeInt.con(2)), new Con(TypeInt.con(3))))));
303  T2 t1 = HM4.hm(syn);
304  assertEquals("3",t1.p());
305  }
306 
307  // Take 2nd element of pair, and applies a function.
308  // let map = fn parg fun => (fun (cdr parg))
309  // Some pairs:
310  // let intz = (pair2 false 3)
311  // let strz = (pair2 false "abc")
312  // in pair(map(str,intz),map(isempty,strz))
313  // Expects: ("2",false)
314  @Test
315  public void test19() {
316  Syntax syn =
317  new Let("cons", new Lambda2("x","y",
318  new Lambda("cadr",new Apply(new Ident("cadr"),new Ident("x"),new Ident("y")))),
319  new Let("cdr", new Lambda("mycons", new Apply(new Ident("mycons"), new Lambda2("p","q", new Ident("q")))),
320  new Let("map",
321  new Lambda2("fun", "parg",
322  new Apply(new Ident("fun"),
323  new Apply(new Ident("cdr"),new Ident("parg"))
324  )),
325  // in pair(map(),map())
326  new Apply(new Ident("pair2"),
327  new Apply(new Ident("map"), new Ident("str" ), (new Apply(new Ident("cons"),new Con(TypeInt.BOOL),new Con(TypeInt.con(5))))),
328  new Apply(new Ident("map"), new Ident("isempty"), (new Apply(new Ident("cons"),new Con(TypeInt.BOOL),new Con(TypeStr.ABC ))))
329  ))));
330  T2 t1 = HM4.hm(syn);
331  assertEquals("(pair2 str int1)",t1.p());
332  }
333 
334  // Obscure factorial-like
335  @Test
336  public void test20() {
337  // let f0 = fn f x => (if/else3 (==0 x) 1 (f (f0 f (dec x)) 2) ) in f0 *2 99
338  Syntax x =
339  new Let("f0", new Lambda2("f","x",
340  new Apply(new Ident("if/else3"),
341  new Apply(new Ident("==0"), new Ident("x")),
342  new Con(TypeInt.con(1)),
343  new Apply(new Ident("f"),
344  new Apply(new Ident("f0"),
345  new Ident("f"),
346  new Apply(new Ident("dec"), new Ident("x"))),
347  new Con(TypeInt.con(2)))
348  )
349  ),
350  new Apply(new Ident("f0"), new Ident("*2"), new Con(TypeInt.con(99))));
351  T2 t1 = HM4.hm(x);
352  assertEquals("int64",t1.p());
353  }
354 
355 
356  // Obscure factorial-like
357  @Test
358  public void test21() {
359  // let f0 = fn f x => (if/else3 (==0 x) 1 (*2 (f0 f (dec x)) 2) ) in f0 f0 99
360  // let f0 = fn f x => (if/else3 (==0 x) 1 (f (f0 f (dec x)) 2) ) in f0 *2 99
361  Syntax x =
362  new Let("f0", new Lambda2("f","x",
363  new Apply(new Ident("if/else3"),
364  new Apply(new Ident("==0"), new Ident("x")),
365  new Con(TypeInt.con(1)),
366  new Apply(new Ident("*2"),
367  new Apply(new Ident("f0"),
368  new Ident("f"),
369  new Apply(new Ident("dec"), new Ident("x"))),
370  new Con(TypeInt.con(2)))
371  )
372  ),
373  new Apply(new Ident("f0"), new Ident("f0"), new Con(TypeInt.con(99))));
374  T2 t1 = HM4.hm(x);
375  assertEquals("int64",t1.p());
376  }
377 
378  // Mututal recursion
379  @Test
380  public void test22() {
381  /* let is_even =
382  (let is_odd = fn x => (if/else3 (==0 x) false (is_even (dec x)))
383  in fn x => (if/else3 (==0 x) true (is_odd (dec x))))
384  in (is_even 3)
385  */
386  Syntax x = new Let("is_even",
387  new Let("is_odd",
388  new Lambda("n",
389  new Apply(new Ident("if/else3"),
390  new Apply(new Ident("==0"), new Ident("n")),
391  new Con(TypeInt.con(0)),
392  new Apply(new Ident("is_even"),
393  new Apply(new Ident("dec"), new Ident("n"))))),
394  new Lambda("n",
395  new Apply(new Ident("if/else3"),
396  new Apply(new Ident("==0"), new Ident("n")),
397  new Con(TypeInt.con(1)),
398  new Apply(new Ident("is_odd" ),
399  new Apply(new Ident("dec"), new Ident("n")))))
400  ),
401  new Apply(new Ident("is_even"), new Con(TypeInt.con(3))));
402  T2 t1 = HM4.hm(x);
403  assertEquals("int1",t1.p());
404  }
405 
406  // Toss a function into a pair & pull it back out
407  @Test
408  public void test23() {
409  // { g ->
410  // let fgz =
411  // // Hand-rolled cons/cdr
412  // let cons = { x y -> { cadr -> (cadr x y) } }
413  // in let cdr = { mycons -> (mycons { p q -> q}) }
414  // in (cdr (cons 2 {z -> g z}))
415  // in (pair2 (fgz 3) (fgz 5))
416  // }
417  Syntax syn =
418  new Lambda("g",
419  new Let("fgz",
420  new Let("cons",
421  new Lambda2("x","y", new Lambda("cadr",new Apply(new Ident("cadr"),new Ident("x"),new Ident("y")))),
422  new Let("cdr",
423  new Lambda("mycons", new Apply(new Ident("mycons"), new Lambda2("p","q", new Ident("q")))),
424  new Apply(new Ident("cdr"),
425  new Apply(new Ident("cons"),
426  new Con(TypeInt.con(2)),
427  new Lambda("z",new Apply(new Ident("g"),new Ident("z"))))))),
428  new Apply(new Ident("pair2"),
429  new Apply(new Ident("fgz"),new Con(TypeInt.con(3))),
430  new Apply(new Ident("fgz"),new Con(TypeInt.con(5))))));
431  T2 t1 = HM4.hm(syn);
432  assertEquals("{ { nint8 -> V31 } -> (pair2 V31 V31) }",t1.p());
433  }
434 
435 }
com.cliffc.aa.HM.TestHM4.test03
void test03()
Definition: TestHM4.java:35
com.cliffc.aa.HM.HM4.reset
static void reset()
Definition: HM4.java:72
com.cliffc.aa.HM.HM7.T2.p
String p()
Definition: HM7.java:1082
com.cliffc
com.cliffc.aa.HM.TestHM4.test16
void test16()
Definition: TestHM4.java:230
com.cliffc.aa.HM.TestHM4.test15
void test15()
Definition: TestHM4.java:210
com.cliffc.aa.HM.HM4
Definition: HM4.java:19
com.cliffc.aa.type.TypeInt
Definition: TypeInt.java:9
com.cliffc.aa.type.TypeFlt
Definition: TypeFlt.java:9
com.cliffc.aa.HM.TestHM4.test04
void test04()
Definition: TestHM4.java:47
com.cliffc.aa.HM.TestHM4.test17
void test17()
Definition: TestHM4.java:254
com.cliffc.aa.type.TypeInt.con
static TypeInt con(long con)
Definition: TypeInt.java:37
com.cliffc.aa.HM.TestHM4.test05
void test05()
Definition: TestHM4.java:65
Test
com.cliffc.aa.HM.TestHM4.test20
void test20()
Definition: TestHM4.java:336
com.cliffc.aa.HM.TestHM4
Definition: TestHM4.java:10
com.cliffc.aa.HM.TestHM4.test13
void test13()
Definition: TestHM4.java:171
com.cliffc.aa.HM.TestHM4.test01
void test01()
Definition: TestHM4.java:21
com.cliffc.aa.type.TypeFlt.con
static Type con(double con)
Definition: TypeFlt.java:36
com.cliffc.aa.HM.TestHM4.test10
void test10()
Definition: TestHM4.java:128
com.cliffc.aa.type.TypeStr.ABC
static final TypeStr ABC
Definition: TypeStr.java:47
com.cliffc.aa.HM.TestHM4.test02
void test02()
Definition: TestHM4.java:28
com.cliffc.aa.HM.HM7.T2
Definition: HM7.java:621
com.cliffc.aa.HM.TestHM4.reset
void reset()
Definition: TestHM4.java:12
com.cliffc.aa.HM.HM4.hm
static T2 hm(Syntax prog)
Definition: HM4.java:22
com.cliffc.aa.HM.TestHM4.test12
void test12()
Definition: TestHM4.java:155
com.cliffc.aa.HM.TestHM4.test06
void test06()
Definition: TestHM4.java:81
com.cliffc.aa.type.TypeStr
Definition: TypeStr.java:14
com.cliffc.aa.HM.TestHM4.test19
void test19()
Definition: TestHM4.java:315
com.cliffc.aa.HM.TestHM4.test00
void test00()
Definition: TestHM4.java:15
com.cliffc.aa.HM.TestHM4.test23
void test23()
Definition: TestHM4.java:408
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.HM.TestHM4.test22
void test22()
Definition: TestHM4.java:380
com.cliffc.aa.HM
Definition: HM.java:1
com.cliffc.aa.HM.TestHM4.test11
void test11()
Definition: TestHM4.java:138
com.cliffc.aa.HM.TestHM4.test21
void test21()
Definition: TestHM4.java:358
com.cliffc.aa.HM.TestHM4.test14
void test14()
Definition: TestHM4.java:193
com.cliffc.aa.HM.TestHM4.test09
void test09()
Definition: TestHM4.java:119
com
com.cliffc.aa.HM.TestHM4.test18
void test18()
Definition: TestHM4.java:292
com.cliffc.aa.HM.TestHM4.test07
void test07()
Definition: TestHM4.java:93
com.cliffc.aa.type.TypeInt.BOOL
static final TypeInt BOOL
Definition: TypeInt.java:43
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.HM.TestHM4.test08
void test08()
Definition: TestHM4.java:104