aa
TestHM9.java
Go to the documentation of this file.
1 package com.cliffc.aa.HM;
2 
3 import com.cliffc.aa.HM.HM9.*;
4 import com.cliffc.aa.type.*;
5 import org.junit.Before;
6 import org.junit.Test;
7 
9 
10 import static org.junit.Assert.assertEquals;
11 
12 public class TestHM9 {
13 
14  @Before public void reset() { HM.reset(); }
15 
16  private void run( String prog, String rez_hm, Type rez_gcp ) {
17  Root syn = HM9.hm(prog);
18  if( HM.DO_HM )
19  assertEquals(rez_hm,syn._hmt.p());
20  if( HM.DO_GCP )
21  assertEquals(rez_gcp,syn.flow_type());
22  }
23  // Simple no-arg signature returning the type
24  private static TypeFunSig tfs(Type ret) {
26  }
27 
31  private static final TypeMemPtr tuple55 = TypeMemPtr.make(7,TypeStruct.make(TypeInt.con(5),TypeInt.con(5)));
32  private static final TypeFunSig ret_tuple2 = tfs(tuple2);
33  private static final String[] XY = new String[]{"^","x","y"};
34  private static final String[] N1V1 = new String[]{"^","n1","v1"};
36 
37  @Test(expected = RuntimeException.class)
38  public void test00() { run( "fred",null,null); }
39 
40  @Test public void test01() { run( "3" ,
41  "3", TypeInt.con(3)); }
42 
43  @Test public void test02() { run( "(pair1 3)" ,
44  "{ A -> ( 3, $A)[7] }", tfs(TypeMemPtr.make(7,TypeStruct.make(TypeInt.con(3),Type.SCALAR)))); }
45 
46  @Test public void test03() { run( "{ z -> (pair (z 0) (z \"abc\")) }" ,
47  "{ { *[0,4]\"abc\"? -> A } -> ( $A, $A)[7] }", tfs(tuple2)); }
48 
49  @Test public void test04() { run( "fact = { n -> (if (?0 n) 1 (* n (fact (dec n))))}; fact",
50  "{ int64 -> int64 }", tfs(TypeInt.INT64) ); }
51 
52  // Because {y->y} is passed in, all 'y' types must agree.
53  // This unifies 3 and "abc" which results in 'all'
54  @Test public void test05() {
55  Root syn = HM9.hm("({ x -> (pair (x 3) (x 5)) } {y->y})");
56  if( HM.DO_HM )
57  assertEquals("( nint8, nint8)[7]",syn._hmt.p());
58  if( HM.DO_GCP )
59  if( HM.DO_HM )
60  assertEquals(tuple82,syn.flow_type());
61  else
62  assertEquals(tuple82,syn.flow_type());
63  }
64 
65  @Test public void test06() {
66  Root syn = HM9.hm("id={x->x}; (pair (id 3) (id \"abc\"))");
67  if( HM.DO_HM ) // HM is sharper here than in test05, because id is generalized per each use site
68  assertEquals("( 3, *[4]\"abc\")[7]",syn._hmt.p());
69  if( HM.DO_GCP )
70  if( HM.DO_HM )
72  else
73  assertEquals(tuplen2,syn.flow_type());
74  }
75 
76  // recursive unification; normal H-M fails here.
77  @Test public void test07() { run( "{ f -> (f f) }",
78  // We can argue the pretty-print should print:
79  // " A:{ $A -> B }"
80  "{ A:{ $A -> B } -> $B }", tfs(Type.SCALAR) ); }
81 
82  @Test public void test08() { run( "g = {f -> 5}; (g g)",
83  "5", TypeInt.con(5)); }
84 
85  // example that demonstrates generic and non-generic variables:
86  @Test public void test09() { run( "{ g -> f = { x -> g }; (pair (f 3) (f \"abc\"))}",
87  "{ A -> ( $A, $A)[7] }", ret_tuple2); }
88 
89  @Test public void test10() { run( "{ f g -> (f g)}",
90  "{ { A -> B } $A -> $B }", tfs(Type.SCALAR) ); }
91 
92  // Function composition
93  @Test public void test11() { run( "{ f g -> { arg -> (g (f arg))} }",
94  "{ { A -> B } { $B -> C } -> { $A -> $C } }", tfs(tfs(Type.SCALAR))); }
95 
96  // Stacked functions ignoring all function arguments
97  @Test public void test12() { run( "map = { fun -> { x -> 2 } }; ((map 3) 5)",
98  "2", TypeInt.con(2)); }
99 
100  // map takes a function and an element (collection?) and applies it (applies to collection?)
101  @Test public void test13() { run( "map = { fun -> { x -> (fun x)}}; { p -> 5 }",
102  "{ A -> 5 }", tfs(TypeInt.con(5))); }
103 
104  // Looking at when tvars are duplicated ("fresh" copies made).
105  // This is the "map" problem with a scalar instead of a collection.
106  // Takes a '{a->b}' and a 'a' for a couple of different prims.
107  @Test public void test14() {
108  Root syn = HM9.hm("map = { fun -> { x -> (fun x)}};"+
109  "(pair ((map str) 5) ((map factor) 2.3))");
110  if( HM.DO_HM )
111  assertEquals("( *[4]str, flt64)[7]",syn._hmt.p());
112  if( HM.DO_GCP )
113  if( HM.DO_HM )
115  else
116  assertEquals(tuple2,syn.flow_type());
117  }
118 
119  // map takes a function and an element (collection?) and applies it (applies to collection?)
120  @Test public void test15() { run("map = { fun x -> (fun x)}; (map {a->3} 5)",
121  "3", TypeInt.con(3)); }
122 
123  // map takes a function and an element (collection?) and applies it (applies to collection?)
124  @Test public void test16() { run("map = { fun x -> (fun x)}; (map { a-> (pair a a)} 5)",
125  "( 5, 5)[7]", tuple55); }
126 
127  @Test public void test17() { run("fcn = { p -> { a -> (pair a a) }};"+
128  "map = { fun x -> (fun x)};"+
129  "{ q -> (map (fcn q) 5)}",
130  "{ A -> ( 5, 5)[7] }", tfs(tuple55)); }
131 
132  // Checking behavior when using "if" to merge two functions with sufficiently
133  // different signatures, then attempting to pass them to a map & calling internally.
134  // fcn takes a predicate 'p' and returns one of two fcns.
135  // let fcn = { p -> (if p {a -> pair[a,a ]}
136  // {b -> pair[b,pair[3,b]]}) } in
137  // map takes a function and an element (collection?) and applies it (applies to collection?)
138  // let map = { fun x -> (fun x) }
139  // in { q -> ((map (fcn q)) 5) }
140  // Should return { q -> q ? [5,5] : [5,[3,5]] }
141  // Ultimately, unifies "a" with "pair[3,a]" which throws recursive unification.
142  @Test public void test18() {
143  Root syn = HM9.hm("fcn = {p -> (if p {a -> (pair a a)} {b -> (pair b (pair 3 b))})};"+
144  "map = { fun x -> (fun x)};"+
145  "{ q -> (map (fcn q) 5)}");
146  if( HM.DO_HM )
147  assertEquals("{ A -> ( B:Cannot unify A:( 3, $A)[7] and 5, $B)[7] }",syn._hmt.p());
148  if( HM.DO_GCP )
149  if( HM.DO_HM )
151  else
152  assertEquals(tfs(TypeMemPtr.make(7,TypeStruct.make(TypeInt.con(5),Type.NSCALR))),syn.flow_type());
153  }
154 
155  @Test public void test19() { run("cons ={x y-> {cadr -> (cadr x y)}};"+
156  "cdr ={mycons -> (mycons { p q -> q})};"+
157  "(cdr (cons 2 3))",
158  "3", TypeInt.con(3)); }
159 
160  // Take 2nd element of pair, and applies a function.
161  // let map = fn parg fun => (fun (cdr parg))
162  // Some pairs:
163  // let intz = (pair2 false 3)
164  // let strz = (pair2 false "abc")
165  // in pair(map(str,intz),map(isempty,strz))
166  // Expects: ("2",false)
167  @Test public void test20() {
168  Root syn = HM9.hm("cons ={x y-> {cadr -> (cadr x y)}};"+
169  "cdr ={mycons -> (mycons { p q -> q})};"+
170  "map ={fun parg -> (fun (cdr parg))};"+
171  "(pair (map str (cons 0 5)) (map isempty (cons 0 \"abc\")))");
172  if( HM.DO_HM )
173  assertEquals("( *[4]str, int1)[7]",syn._hmt.p());
174  if( HM.DO_GCP )
175  if( HM.DO_HM )
177  else
178  assertEquals(tuple2,syn.flow_type());
179  }
180 
181  // Obscure factorial-like
182  @Test public void test21() { run("f0 = { f x -> (if (?0 x) 1 (f (f0 f (dec x)) 2))}; (f0 * 99)",
183  "int64", TypeInt.INT64); }
184 
185  // Obscure factorial-like
186  // let f0 = fn f x => (if (?0 x) 1 (* (f0 f (dec x)) 2) ) in f0 f0 99
187  // let f0 = fn f x => (if (?0 x) 1 (f (f0 f (dec x)) 2) ) in f0 * 99
188  @Test public void test22() { run("f0 = { f x -> (if (?0 x) 1 (* (f0 f (dec x)) 2))}; (f0 f0 99)",
189  "int64", TypeInt.INT64); }
190 
191  // Mutual recursion
192  @Test public void test23() { run("is_even = "+
193  " is_odd = { n -> (if (?0 n) 0 (is_even (dec n)))}; "+
194  " { n -> (if (?0 n) 1 (is_odd (dec n)))};"+
195  "(is_even 3)" ,
196  "int1", TypeInt.BOOL); }
197 
198  // Toss a function into a pair & pull it back out
199  @Test public void test24() { run("{ g -> fgz = "+
200  " cons = {x y -> {cadr -> (cadr x y)}};"+
201  " cdr = {mycons -> (mycons { p q -> q})};"+
202  " (cdr (cons 2 { z -> (g z) }));"+
203  " (pair (fgz 3) (fgz 5))"+
204  "}"
205  ,
206  "{ { nint8 -> A } -> ( $A, $A)[7] }", tfs(tuple2)); }
207 
208  // Basic structure test
209  @Test public void test25() { run("@{x=2, y=3}",
210  "@{ x = 2, y = 3}[9]",
212  ); }
213 
214  // Basic field test
215  @Test public void test26() { run(".x @{x =2, y =3}",
216  "2", TypeInt.con(2)); }
217 
218  // Basic field test
219  @Test public void test27() { run(".x 5",
220  "Missing field x in 5", Type.SCALAR); }
221 
222  // Basic field test.
223  @Test public void test28() { run(".x @{ y =3}",
224  "Missing field x in @{ y = 3}[9]",
225  Type.SCALAR); }
226 
227  @Test public void test29() { run("{ g -> @{x=g, y=g}}",
228  "{ A -> @{ x = $A, y = $A}[9] }", tfs(tuple9)); }
229 
230  // Load common field 'x', ignoring mismatched fields y and z
231  @Test public void test30() { run("{ pred -> .x (if pred @{x=2,y=3} @{x=3,z= \"abc\"}) }",
232  "{ A -> nint8 }", tfs(TypeInt.NINT8)); }
233 
234  // Load some fields from an unknown struct: area of a rectangle.
235  // Since no nil-check, correctly types as needing a not-nil input.
236  @Test public void test31() { run("{ sq -> (* .x sq .y sq) }", // { sq -> sq.x * sq.y }
237  "{ @{ x = int64, y = int64}[] -> int64 }", tfs(TypeInt.INT64)); }
238 
239  private static TypeMemPtr build_cycle( int alias, boolean nil, Type fld ) {
240  // Build a cycle of length 2.
241  BitsAlias aliases = BitsAlias.make0(alias);
242  if( nil ) aliases = aliases.meet_nil();
243  TypeMemPtr cycle_ptr0 = TypeMemPtr.make(aliases,TypeObj.XOBJ);
244  TypeStruct cycle_str1 = TypeStruct.make(TypeFld.NO_DISP,TypeFld.malloc("n1",cycle_ptr0,1),TypeFld.malloc("v1",fld,1));
245  TypeMemPtr cycle_ptr1 = TypeMemPtr.make(aliases,cycle_str1);
246  TypeStruct cycle_str2 = TypeStruct.make(TypeFld.NO_DISP,TypeFld.malloc("n1",cycle_ptr1,1),TypeFld.malloc("v1",fld,1));
247  TypeStruct cycle_strn = cycle_str2.approx(1,alias);
248  TypeMemPtr cycle_ptrn = (TypeMemPtr)cycle_strn.at(1);
249  return cycle_ptrn;
250  }
251 
252 
253  // Recursive linked-list discovery, with no end clause. Since this code has
254  // no exit (its an infinite loop, endlessly reading from an infinite input
255  // and writing an infinite output), gcp gets a cyclic approximation.
256  @Test public void test32() {
257  Root syn = HM9.hm("map = { fcn lst -> @{ n1 = (map fcn .n0 lst), v1 = (fcn .v0 lst) } }; map");
258  if( HM.DO_HM )
259  assertEquals("{ { A -> B } C:@{ n0 = $C, v0 = $A}[] -> D:@{ n1 = $D, v1 = $B}[9] }",syn._hmt.p());
260  if( HM.DO_GCP )
261  // Build a cycle of length 2, without nil.
262  assertEquals(tfs(build_cycle(9,false,Type.SCALAR)),syn.flow_type());
263  }
264 
265  // Recursive linked-list discovery, with nil. Note that the output memory
266  // has the output memory alias, but not the input memory alias (which must be
267  // made before calling 'map').
268  @Test public void test33() {
269  Root syn = HM9.hm("map = { fcn lst -> (if lst @{ n1=(map fcn .n0 lst), v1=(fcn .v0 lst) } 0) }; map");
270  if( HM.DO_HM )
271  assertEquals("{ { A -> B } C:@{ n0 = $C, v0 = $A}[0] -> D:@{ n1 = $D, v1 = $B}[0,9] }",syn._hmt.p());
272  if( HM.DO_GCP )
273  // Build a cycle of length 2, with nil.
274  assertEquals(tfs(build_cycle(9,true,Type.SCALAR)),syn.flow_type());
275  }
276 
277  // Recursive linked-list discovery, with no end clause
278  @Test public void test34() {
279  Root syn = HM9.hm("map = { fcn lst -> (if lst @{ n1 = (map fcn .n0 lst), v1 = (fcn .v0 lst) } 0) }; (map dec @{n0 = 0, v0 = 5})");
280  if( HM.DO_HM )
281  assertEquals("A:@{ n1 = $A, v1 = int64}[0,9]",syn._hmt.p());
282  if( HM.DO_GCP )
283  assertEquals(build_cycle(9,true,TypeInt.con(4)),syn.flow_type());
284  }
285 
286  // try the worse-case expo blow-up test case from SO
287  @Test public void test35() {
288  TypeFunPtr tfp = TypeFunPtr.make(15,3,Type.ANY);
289  TypeMemPtr tmp0 = TypeMemPtr.make(8,TypeStruct.make(tfp ,tfp ,tfp ));
290  TypeMemPtr tmp1 = TypeMemPtr.make(8,TypeStruct.make(tmp0,tmp0,tmp0));
291  TypeMemPtr tmp2 = TypeMemPtr.make(8,TypeStruct.make(tmp1,tmp1,tmp1));
292 
293  run("p0 = { x y z -> (triple x y z) };"+
294  "p1 = (triple p0 p0 p0);"+
295  "p2 = (triple p1 p1 p1);"+
296  "p3 = (triple p2 p2 p2);"+
297  "p3",
298  "( ( ( { A B C -> ( $A, $B, $C)[8] }, { D E F -> ( $D, $E, $F)[8] }, { G H I -> ( $G, $H, $I)[8] })[8], ( { J K L -> ( $J, $K, $L)[8] }, { M N O -> ( $M, $N, $O)[8] }, { P Q R -> ( $P, $Q, $R)[8] })[8], ( { S T U -> ( $S, $T, $U)[8] }, { V21 V22 V23 -> ( $V21, $V22, $V23)[8] }, { V24 V25 V26 -> ( $V24, $V25, $V26)[8] })[8])[8], ( ( { V27 V28 V29 -> ( $V27, $V28, $V29)[8] }, { V30 V31 V32 -> ( $V30, $V31, $V32)[8] }, { V33 V34 V35 -> ( $V33, $V34, $V35)[8] })[8], ( { V36 V37 V38 -> ( $V36, $V37, $V38)[8] }, { V39 V40 V41 -> ( $V39, $V40, $V41)[8] }, { V42 V43 V44 -> ( $V42, $V43, $V44)[8] })[8], ( { V45 V46 V47 -> ( $V45, $V46, $V47)[8] }, { V48 V49 V50 -> ( $V48, $V49, $V50)[8] }, { V51 V52 V53 -> ( $V51, $V52, $V53)[8] })[8])[8], ( ( { V54 V55 V56 -> ( $V54, $V55, $V56)[8] }, { V57 V58 V59 -> ( $V57, $V58, $V59)[8] }, { V60 V61 V62 -> ( $V60, $V61, $V62)[8] })[8], ( { V63 V64 V65 -> ( $V63, $V64, $V65)[8] }, { V66 V67 V68 -> ( $V66, $V67, $V68)[8] }, { V69 V70 V71 -> ( $V69, $V70, $V71)[8] })[8], ( { V72 V73 V74 -> ( $V72, $V73, $V74)[8] }, { V75 V76 V77 -> ( $V75, $V76, $V77)[8] }, { V78 V79 V80 -> ( $V78, $V79, $V80)[8] })[8])[8])[8]",
299  tmp2 );
300  }
301 
302  // Need to see if a map call, inlined a few times, 'rolls up'. Sometimes
303  // rolls up, sometimes not; depends on worklist visitation order.
304  @Test public void test36() {
305  Root syn = HM9.hm("map = { lst -> (if lst @{ n1= arg= .n0 lst; (if arg @{ n1=(map .n0 arg), v1=(str .v0 arg)} 0), v1=(str .v0 lst) } 0) }; map");
306  if( HM.DO_HM )
307  assertEquals("{ A:@{ n0 = @{ n0 = $A, v0 = int64}[0], v0 = int64}[0] -> B:@{ n1 = @{ n1 = $B, v1 = *[4]str}[0,9], v1 = *[4]str}[0,10] }",syn._hmt.p());
308  if( HM.DO_GCP ) {
309  TypeStruct cycle_strX;
310  if( true ) {
311  // Unrolled, known to only produce results where either other nested
312  // struct is from a different allocation site.
313  TypeMemPtr cycle_ptr0 = TypeMemPtr.make(BitsAlias.FULL.make(0,10),TypeObj.XOBJ);
314  TypeStruct cycle_str1 = TypeStruct.make(TypeFld.NO_DISP,TypeFld.malloc("n1",cycle_ptr0,1),TypeFld.malloc("v1",TypeMemPtr.STRPTR,1));
315  TypeMemPtr cycle_ptr1 = TypeMemPtr.make(BitsAlias.FULL.make(0, 9),cycle_str1);
316  TypeStruct cycle_str2 = TypeStruct.make(TypeFld.NO_DISP,TypeFld.malloc("n1",cycle_ptr1,1),TypeFld.malloc("v1",TypeMemPtr.STRPTR,1));
317  TypeMemPtr cycle_ptr2 = TypeMemPtr.make(BitsAlias.FULL.make(0,10),cycle_str2);
318  TypeStruct cycle_str3 = TypeStruct.make(TypeFld.NO_DISP,TypeFld.malloc("n1",cycle_ptr2,1),TypeFld.malloc("v1",TypeMemPtr.STRPTR,1));
319  cycle_strX = cycle_str3;
320  } else {
321  // Not unrolled, both structs are folded
322  TypeMemPtr cycle_ptr0 = TypeMemPtr.make(BitsAlias.FULL.make(0,7, 8),TypeObj.XOBJ);
323  TypeStruct cycle_str1 = TypeStruct.make(TypeFld.NO_DISP,TypeFld.malloc("n1",cycle_ptr0,1),TypeFld.malloc("v1",TypeMemPtr.STRPTR,1));
324  TypeMemPtr cycle_ptr1 = TypeMemPtr.make(BitsAlias.FULL.make(0,7, 8),cycle_str1);
325  TypeStruct cycle_str2 = TypeStruct.make(TypeFld.NO_DISP,TypeFld.malloc("n1",cycle_ptr1,1),TypeFld.malloc("v1",TypeMemPtr.STRPTR,1));
326  cycle_strX = cycle_str2;
327  }
328  TypeStruct cycle_strn = cycle_strX.approx(1,9);
329  TypeMemPtr cycle_ptrn = (TypeMemPtr)cycle_strn.at(1);
330  assertEquals(tfs(cycle_ptrn),syn.flow_type());
331  }
332  }
333 
334  @Test public void test37() { run("x = { y -> (x (y y))}; x",
335  "{ A:{ $A -> $A } -> B }", tfs(Type.XSCALAR)); }
336 
337  // Example from SimpleSub requiring 'x' to be both a struct with field
338  // 'v', and also a function type - specifically disallowed in 'aa'.
339  @Test public void test38() { run("{ x -> y = ( x .v x ); 0}",
340  "{ Cannot unify @{ v = A}[] and { A -> B } -> 0 }", tfs(Type.XNIL)); }
341 
342  // Really bad flow-type: function can be called from the REPL with any
343  // argument type - and the worse case will be an error.
344  @Test public void test39() {
345  Root syn = HM9.hm("x = { z -> z}; (x { y -> .u y})");
346  if( HM.DO_HM )
347  assertEquals("{ @{ u = A}[] -> $A }",syn._hmt.p());
348  if( HM.DO_GCP )
349  assertEquals(tfs(Type.SCALAR), syn.flow_type());
350  }
351 
352  // Example from SimpleSub requiring 'x' to be both:
353  // - a recursive self-call function from "w = (x x)": $V66:{ $V66 -> V67 } AND
354  // - a function which takes a struct with field 'u'
355  // The first arg to x is two different kinds of functions, so fails unification.
356  @Test public void test40() {
357  Root syn = HM9.hm("x = w = (x x); { z -> z}; (x { y -> .u y})");
358  if( HM.DO_HM )
359  assertEquals("Cannot unify A:{ $A -> $A } and @{ u = A}[]",syn._hmt.p());
360  if( HM.DO_GCP ) {
361  if( HM.DO_HM ) {
362  assertEquals(tfs(Type.SCALAR), syn.flow_type());
363  } else {
364  assertEquals(Type.SCALAR, syn.flow_type());
365  }
366  }
367  }
368 
369  // Example from test15:
370  // map={lst fcn -> lst ? fcn lst.1};
371  // in_int=(0,2);"+ // List of ints
372  // in_str=(0,"abc");" + // List of strings
373  // out_str = map(in_int,str:{int->str});"+ // Map over ints with int->str conversion, returning a list of strings
374  // out_bool= map(in_str,{str -> str==\"abc\"});"+ // Map over strs with str->bool conversion, returning a list of bools
375  // (out_str,out_bool)",
376  @Test public void test41() {
377  Root syn = HM9.hm("map={lst fcn -> (fcn .y lst) }; "+
378  "in_int=@{ x=0 y=2}; " +
379  "in_str=@{ x=0 y=\"abc\"}; " +
380  "out_str = (map in_int str); " +
381  "out_bool= (map in_str { xstr -> (eq xstr \"def\")}); "+
382  "(pair out_str out_bool)");
383  if( HM.DO_HM )
384  assertEquals("( *[4]str, int1)[7]",syn._hmt.p());
385  if( HM.DO_GCP )
386  if( HM.DO_HM )
388  else
389  assertEquals(tuple2,syn.flow_type());
390  }
391 
392  // CCP Can help HM
393  @Test public void test42() {
394  Root syn = HM9.hm("pred = 0; s1 = @{ x=\"abc\" }; s2 = @{ y=3.4 }; .y (if pred s1 s2)");
395  if( HM.DO_HM ) {
396  if( HM.DO_GCP )
397  assertEquals("3.4000000953674316",syn._hmt.p());
398  else
399  assertEquals("Missing field y in @{ x = *[4]\"abc\"}[9]",syn._hmt.p());
400  }
401  if( HM.DO_GCP )
402  assertEquals(TypeFlt.con(3.4f), syn.flow_type());
403  }
404 
405  // The z-merge is ignored; the last s2 is a fresh (unmerged) copy.
406  @Test public void test43() {
407  Root syn = HM9.hm("pred = 0; s1 = @{ x=\"abc\" }; s2 = @{ y=3.4 }; z = (if pred s1 s2); .y s2");
408  if( HM.DO_HM )
409  assertEquals("3.4000000953674316",syn._hmt.p());
410  if( HM.DO_GCP )
411  assertEquals(TypeFlt.con(3.4f), syn.flow_type());
412  }
413 
414 
415  @Test public void test44() {
416  Root syn = HM9.hm("fun = (if (isempty \"abc\") {x->x} {x->1.2}); (fun @{})");
417  if( HM.DO_HM ) {
418  if( HM.DO_GCP )
419  assertEquals("1.2000000476837158",syn._hmt.p());
420  else
421  assertEquals("Cannot unify 1.2000000476837158 and )[9]",syn._hmt.p());
422  }
423  if( HM.DO_GCP )
424  assertEquals(TypeFlt.con(1.2f), syn.flow_type());
425  }
426 
427 
428  // Requires a combo of HM and GCP to get the good answer
429  @Test public void test45() {
430  Root syn = HM9.hm(
431 "id = {x -> x};" +
432 "loop = { name cnt ->" +
433 " (if cnt " +
434 " (loop" +
435 " fltfun = (if name id {x->3});" +
436 " (fltfun \"abc\")" +
437 " (dec cnt)" +
438 " )" +
439 " name" +
440 " )"+
441 "};" +
442 "(loop \"def\" (id 2))");
443  if( HM.DO_HM )
444  assertEquals(HM.DO_GCP
445  ? "*[4]str" // Both HM and GCP
446  : "Cannot unify *[4]\"abc\" and 3", // HM alone cannot do this one
447  syn._hmt.p());
448  if( HM.DO_GCP )
449  assertEquals(HM.DO_HM
450  ? TypeMemPtr.STRPTR // Both HM and GCP
451  : Type.NSCALR, // GCP alone gets a very weak answer
452  syn.flow_type());
453  }
454 
455 
456  // Basic nil test
457  @Test public void test46() { run(".x 0",
458  "May be nil when loading field x", Type.XSCALAR); }
459 
460  // Basic nil test
461  @Test public void test47() { run("{ pred -> .x (if pred @{x=3} 0)}",
462  "{ A -> May be nil when loading field x }", tfs(TypeInt.con(3))); }
463 
464  // Basic uplifting after check
465  @Test public void test48() { run("{ pred -> tmp=(if pred @{x=3} 0); (if tmp .x tmp 4) }",
466  "{ A -> nint8 }", tfs(TypeInt.NINT8)); }
467 
468 
469  // map is parametric in nil-ness
470  @Test public void test49() {
471  Root syn = HM9.hm("{ pred -> \n"+
472  " map = { fun x -> (fun x) };\n" +
473  " (pair (map {str0 -> .x str0 } @{x = 3} )\n" +
474  " (map {str1 -> (if str1 .x str1 4)} (if pred @{x = 5} 0))\n" +
475  " )\n"+
476  "}");
477  if( HM.DO_HM )
478  assertEquals("{ A -> ( 3, nint8)[7] }",syn._hmt.p());
479  if( HM.DO_GCP )
482  }
483 
484  // map is parametric in nil-ness. Verify still nil-checking.
485  @Test public void test50() {
486  Root syn = HM9.hm("{ pred -> \n"+
487  " map = { fun x -> (fun x) };\n" +
488  " (pair (map {str0 -> .x str0 } @{x = 3} )\n" +
489  " (map {str1 -> .x str1 } (if pred @{x = 5} 0))\n" +
490  " )\n"+
491  "}");
492  if( HM.DO_HM )
493  assertEquals("{ A -> May be nil when loading field x }",syn._hmt.p());
494  if( HM.DO_GCP )
497  }
498 
499 }
com.cliffc.aa.type.BitsAlias.FULL
static BitsAlias FULL
Definition: BitsAlias.java:27
com.cliffc.aa.HM.TestHM9.tuple55
static final TypeMemPtr tuple55
Definition: TestHM9.java:31
com.cliffc.aa.type.Type.NSCALR
static final Type NSCALR
Definition: Type.java:330
com.cliffc.aa.HM.TestHM9.test14
void test14()
Definition: TestHM9.java:107
com.cliffc.aa.HM.TestHM9.test02
void test02()
Definition: TestHM9.java:43
com.cliffc.aa.type.TypeFunPtr
Definition: TypeFunPtr.java:23
com.cliffc.aa.HM.HM.Root
Definition: HM.java:735
com.cliffc.aa.HM.TestHM9.test23
void test23()
Definition: TestHM9.java:192
com.cliffc.aa.type.TypeTuple.make_args
static TypeTuple make_args(Type[] ts)
Definition: TypeTuple.java:106
com.cliffc.aa.HM.TestHM9.test00
void test00()
Definition: TestHM9.java:38
com.cliffc.aa.type.TypeTuple.make_ret
static TypeTuple make_ret(Type trez)
Definition: TypeTuple.java:120
com.cliffc.aa.HM.TestHM9.reset
void reset()
Definition: TestHM9.java:14
com.cliffc.aa.type.Type.SCALAR
static final Type SCALAR
Definition: Type.java:328
com.cliffc
com.cliffc.aa.HM.TestHM9.test37
void test37()
Definition: TestHM9.java:334
com.cliffc.aa.HM.TestHM9.test41
void test41()
Definition: TestHM9.java:376
com.cliffc.aa.type.Bits.make
B make(boolean any, long[] bits)
Definition: Bits.java:154
com.cliffc.aa.type.TypeFld
Definition: TypeFld.java:12
com.cliffc.aa.type.Type.XSCALAR
static final Type XSCALAR
Definition: Type.java:329
com.cliffc.aa.HM.TestHM9.test26
void test26()
Definition: TestHM9.java:215
com.cliffc.aa.type.TypeInt
Definition: TypeInt.java:9
com.cliffc.aa.HM.TestHM9.test36
void test36()
Definition: TestHM9.java:304
com.cliffc.aa.HM.TestHM9
Definition: TestHM9.java:12
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.HM.HM.Root.flow_type
Type flow_type()
Definition: HM.java:775
com.cliffc.aa.type.TypeFunSig.make
static TypeFunSig make(String[] args, TypeTuple formals, TypeTuple ret)
Definition: TypeFunSig.java:71
com.cliffc.aa.type.TypeFlt
Definition: TypeFlt.java:9
com.cliffc.aa.type.BitsAlias
Definition: BitsAlias.java:8
com.cliffc.aa.type.TypeTuple
Definition: TypeTuple.java:11
com.cliffc.aa.HM.TestHM9.test31
void test31()
Definition: TestHM9.java:236
com.cliffc.aa.HM.TestHM9.test29
void test29()
Definition: TestHM9.java:227
com.cliffc.aa.type.TypeFld.NO_DISP
static final TypeFld NO_DISP
Definition: TypeFld.java:170
com.cliffc.aa.HM.TestHM9.test22
void test22()
Definition: TestHM9.java:188
com.cliffc.aa.type.TypeInt.con
static TypeInt con(long con)
Definition: TypeInt.java:37
com.cliffc.aa.HM.TestHM9.build_cycle
static TypeMemPtr build_cycle(int alias, boolean nil, Type fld)
Definition: TestHM9.java:239
com.cliffc.aa.HM.HM
Definition: HM.java:84
com.cliffc.aa.HM.TestHM9.test48
void test48()
Definition: TestHM9.java:465
com.cliffc.aa.HM.TestHM9.test38
void test38()
Definition: TestHM9.java:339
com.cliffc.aa.type.Type.ANY
static final Type ANY
Definition: Type.java:325
Test
com.cliffc.aa.type.TypeStruct
A memory-based collection of optionally named fields.
Definition: TypeStruct.java:50
com.cliffc.aa.HM.TestHM9.test04
void test04()
Definition: TestHM9.java:49
com.cliffc.aa.HM.HM.DO_HM
static final boolean DO_HM
Definition: HM.java:91
com.cliffc.aa.HM.TestHM9.test03
void test03()
Definition: TestHM9.java:46
com.cliffc.aa.type.TypeStruct.at
Type at(int idx)
Definition: TypeStruct.java:1013
com.cliffc.aa.HM.TestHM9.test47
void test47()
Definition: TestHM9.java:461
com.cliffc.aa.HM.TestHM9.test09
void test09()
Definition: TestHM9.java:86
com.cliffc.aa.HM.TestHM9.test39
void test39()
Definition: TestHM9.java:344
com.cliffc.aa.HM.TestHM9.tuple9
static final TypeMemPtr tuple9
Definition: TestHM9.java:35
com.cliffc.aa.type.TypeInt.INT64
static final TypeInt INT64
Definition: TypeInt.java:39
com.cliffc.aa.HM.TestHM9.test11
void test11()
Definition: TestHM9.java:93
com.cliffc.aa.HM.TestHM9.test33
void test33()
Definition: TestHM9.java:268
com.cliffc.aa.type.TypeObj
Definition: TypeObj.java:15
com.cliffc.aa.HM.TestHM9.XY
static final String[] XY
Definition: TestHM9.java:33
com.cliffc.aa.type.TypeFlt.con
static Type con(double con)
Definition: TypeFlt.java:36
com.cliffc.aa.HM.TestHM9.test30
void test30()
Definition: TestHM9.java:231
com.cliffc.aa.HM.HM.T2.p
String p()
Definition: HM.java:2205
com.cliffc.aa.HM.TestHM9.test16
void test16()
Definition: TestHM9.java:124
com.cliffc.aa.HM.TestHM9.test50
void test50()
Definition: TestHM9.java:485
com.cliffc.aa.HM.TestHM9.test28
void test28()
Definition: TestHM9.java:223
com.cliffc.aa.HM.TestHM9.test24
void test24()
Definition: TestHM9.java:199
com.cliffc.aa.HM.TestHM9.test13
void test13()
Definition: TestHM9.java:101
com.cliffc.aa.type.Type.XNSCALR
static final Type XNSCALR
Definition: Type.java:331
com.cliffc.aa.type.TypeObj.XOBJ
static final TypeObj XOBJ
Definition: TypeObj.java:47
com.cliffc.aa.HM.TestHM9.test12
void test12()
Definition: TestHM9.java:97
com.cliffc.aa.HM.TestHM9.test01
void test01()
Definition: TestHM9.java:40
com.cliffc.aa.HM.HM.Syntax._hmt
T2 _hmt
Definition: HM.java:343
com.cliffc.aa.HM.TestHM9.tfs
static TypeFunSig tfs(Type ret)
Definition: TestHM9.java:24
com.cliffc.aa.type.TypeStr.ABC
static final TypeStr ABC
Definition: TypeStr.java:47
com.cliffc.aa.HM.TestHM9.tuple82
static final TypeMemPtr tuple82
Definition: TestHM9.java:30
com.cliffc.aa.HM.TestHM9.tuple2
static final TypeMemPtr tuple2
Definition: TestHM9.java:28
com.cliffc.aa.type.TypeInt.NINT8
static final TypeInt NINT8
Definition: TypeInt.java:47
com.cliffc.aa.HM.TestHM9.test06
void test06()
Definition: TestHM9.java:65
com.cliffc.aa.type.Bits.meet_nil
B meet_nil()
Definition: Bits.java:212
com.cliffc.aa.HM.TestHM9.test34
void test34()
Definition: TestHM9.java:278
com.cliffc.aa.type.TypeFunPtr.make
static TypeFunPtr make(BitsFun fidxs, int nargs, Type disp)
Definition: TypeFunPtr.java:67
com.cliffc.aa.HM.HM9
Definition: HM9.java:71
com.cliffc.aa.type.TypeStruct.flds
static TypeFld[] flds(Type t1)
Definition: TypeStruct.java:184
com.cliffc.aa.HM.TestHM9.test42
void test42()
Definition: TestHM9.java:393
com.cliffc.aa.HM.TestHM9.test46
void test46()
Definition: TestHM9.java:457
com.cliffc.aa.type.TypeStr
Definition: TypeStr.java:14
com.cliffc.aa.HM.HM9.hm
static Root hm(String sprog)
Definition: HM9.java:81
com.cliffc.aa.type.TypeFld.malloc
static TypeFld malloc(String fld, Type t, Access access, int order)
Definition: TypeFld.java:53
com.cliffc.aa.HM.TestHM9.test43
void test43()
Definition: TestHM9.java:406
com.cliffc.aa.type.TypeStruct.approx
TypeStruct approx(int cutoff, int alias)
Definition: TypeStruct.java:477
com.cliffc.aa.HM.TestHM9.tuplen2
static final TypeMemPtr tuplen2
Definition: TestHM9.java:29
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.type.BitsAlias.make0
static BitsAlias make0(int bit)
Definition: BitsAlias.java:72
com.cliffc.aa.HM.TestHM9.test10
void test10()
Definition: TestHM9.java:89
com.cliffc.aa.HM
Definition: HM.java:1
com.cliffc.aa.type.TypeFunSig
Definition: TypeFunSig.java:10
com.cliffc.aa.HM.TestHM9.test19
void test19()
Definition: TestHM9.java:155
com.cliffc.aa.HM.HM.DO_GCP
static final boolean DO_GCP
Definition: HM.java:92
com.cliffc.aa.HM.TestHM9.test17
void test17()
Definition: TestHM9.java:127
com.cliffc.aa.HM.TestHM9.N1V1
static final String[] N1V1
Definition: TestHM9.java:34
com.cliffc.aa.type.TypeStruct.make
static TypeStruct make(String fld_name, Type t)
Definition: TypeStruct.java:190
com.cliffc.aa.HM.TestHM9.test49
void test49()
Definition: TestHM9.java:470
com.cliffc.aa.type.Type.XNIL
static final Type XNIL
Definition: Type.java:333
com.cliffc.aa.HM.TestHM9.test07
void test07()
Definition: TestHM9.java:77
com.cliffc.aa.type.TypeFld.Access
Definition: TypeFld.java:109
com.cliffc.aa.type.TypeMemPtr.STRPTR
static final TypeMemPtr STRPTR
Definition: TypeMemPtr.java:97
com.cliffc.aa.HM.TestHM9.test25
void test25()
Definition: TestHM9.java:209
com.cliffc.aa.HM.TestHM9.test27
void test27()
Definition: TestHM9.java:219
com.cliffc.aa.HM.TestHM9.run
void run(String prog, String rez_hm, Type rez_gcp)
Definition: TestHM9.java:16
com
com.cliffc.aa.HM.TestHM9.test08
void test08()
Definition: TestHM9.java:82
com.cliffc.aa.HM.TestHM9.test40
void test40()
Definition: TestHM9.java:356
com.cliffc.aa.HM.HM.reset
static void reset()
Definition: HM.java:143
com.cliffc.aa.HM.TestHM9.test44
void test44()
Definition: TestHM9.java:415
com.cliffc.aa.HM.TestHM9.test32
void test32()
Definition: TestHM9.java:256
com.cliffc.aa.type.TypeInt.BOOL
static final TypeInt BOOL
Definition: TypeInt.java:43
com.cliffc.aa.HM.TestHM9.test15
void test15()
Definition: TestHM9.java:120
com.cliffc.aa.HM.TestHM9.test45
void test45()
Definition: TestHM9.java:429
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.HM.TestHM9.test21
void test21()
Definition: TestHM9.java:182
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.HM.TestHM9.test35
void test35()
Definition: TestHM9.java:287
com.cliffc.aa.type.TypeFlt.FLT64
static final TypeFlt FLT64
Definition: TypeFlt.java:38
com.cliffc.aa.HM.TestHM9.test18
void test18()
Definition: TestHM9.java:142
com.cliffc.aa.HM.TestHM9.ret_tuple2
static final TypeFunSig ret_tuple2
Definition: TestHM9.java:32
com.cliffc.aa.HM.TestHM9.test05
void test05()
Definition: TestHM9.java:54
com.cliffc.aa.type.TypeMemPtr.make
static TypeMemPtr make(BitsAlias aliases, TypeObj obj)
Definition: TypeMemPtr.java:66
com.cliffc.aa.HM.TestHM9.test20
void test20()
Definition: TestHM9.java:167