aa
HM5.java
Go to the documentation of this file.
1 package com.cliffc.aa.HM;
2 
3 import com.cliffc.aa.type.*;
4 import com.cliffc.aa.util.*;
5 import org.jetbrains.annotations.NotNull;
6 
7 import java.util.*;
8 
9 import static com.cliffc.aa.AA.unimpl;
10 
11 // Hindley-Milner typing. Complete stand-alone, for research. MEETs base
12 // types, instead of declaring type error. Requires SSA renumbering; looks
13 // 'up' the Syntax tree for variables instead of building a 'nongen' set.
14 //
15 // T2 types form a Lattice, with 'unify' same as 'meet'. T2's form a DAG
16 // (cycles if i allow recursive unification) with sharing. Each Syntax has a
17 // T2, and the forest of T2s can share. Leaves of a T2 can be either a simple
18 // concrete base type, or a sharable leaf. Unify is structural, and where not
19 // unifyable the union is replaced with an Error.
20 
21 // Lazily computes 'Fresh' copies instead of eagerly.
22 
23 public class HM5 {
24  static final HashMap<String,T2> PRIMS = new HashMap<>();
25  static boolean DEBUG_LEAKS=false;
26 
27  public static T2 hm( Syntax prog) {
28  Worklist work = new Worklist();
29 
30  // Simple types
31  T2 bool = T2.make_base(TypeInt.BOOL);
32  T2 int64 = T2.make_base(TypeInt.INT64);
33  T2 flt64 = T2.make_base(TypeFlt.FLT64);
35 
36  // Primitives
37  T2 var1 = T2.make_leaf();
38  T2 var2 = T2.make_leaf();
39 
40  PRIMS.put("pair1",T2.make_fun(var1, T2.make_fun(var2, T2.prim("pair",var1,var2) )));
41  PRIMS.put("pair",T2.make_fun(var1, var2, T2.prim("pair",var1,var2) ));
42 
43  PRIMS.put("if/else",T2.make_fun(bool,var1,var1,var1));
44 
45  PRIMS.put("dec",T2.make_fun(int64,int64));
46  PRIMS.put("*" ,T2.make_fun(int64,int64,int64));
47  PRIMS.put("==0",T2.make_fun(int64,bool));
48  PRIMS.put("isempty",T2.make_fun(strp,bool));
49 
50  // Print a string; int->str
51  PRIMS.put("str",T2.make_fun(int64,strp));
52  // Factor; FP div/mod-like operation
53  PRIMS.put("factor",T2.make_fun(flt64,T2.prim("divmod",flt64,flt64)));
54 
55  // Prep for SSA: pre-gather all the (unique) ids
56  int cnt_syns = prog.prep_tree(null,null,work);
57  int init_T2s = T2.CNT;
58 
59  int cnt=0, DEBUG_CNT=-1;
60  while( work.len()>0 ) { // While work
61  int oldcnt = T2.CNT; // Used for cost-check when no-progress
62  Syntax syn = work.pop(); // Get work
63  T2 old = syn._t; // Old value for progress assert
64  if( cnt==DEBUG_CNT )
65  System.out.println("break here");
66  if( syn.hm(work) ) { // Compute a new HM type and check for progress
67  assert !syn.debug_find().unify(old.find(),null);// monotonic: unifying with the result is no-progress
68  syn.add_kids(work); // Push children on worklist
69  syn.add_occurs(work); // Push occurs-check ids on worklist
70  if( syn._par !=null ) work.push(syn._par); // Parent updates
71  } else {
72  assert !DEBUG_LEAKS || oldcnt==T2.CNT; // No-progress consumes no-new-T2s
73  }
74  // VERY EXPENSIVE ASSERT: O(n^2). Every Syntax that makes progress is on the worklist
75  //assert prog.more_work(work);
76  cnt++;
77  }
78  assert prog.more_work(work);
79 
80  //System.out.println("Initial T2s: "+init_T2s+", Prog size: "+cnt_syns+", worklist iters: "+cnt+", T2s: "+T2.CNT);
81  return prog._t;
82  }
83  static void reset() { PRIMS.clear(); T2.reset(); }
84 
85  // Worklist of Syntax nodes
86  private static class Worklist {
87  public int _cnt;
88  private final Ary<Syntax> _ary = new Ary<>(Syntax.class); // For picking random element
89  private final HashSet<Syntax> _work = new HashSet<>(); // For preventing dups
90  public int len() { return _ary.len(); }
91  public void push(Syntax s) { if( !_work.contains(s) ) _work.add(_ary.push(s)); }
92  //public Syntax pop() { Syntax s = _ary.pop();_cnt++; _work.remove(s); return s; }
93  public Syntax pop() { Syntax s = _ary.del( _cnt++%_ary._len); _work.remove(s); return s; }
94  public boolean has(Syntax s) { return _work.contains(s); }
95  public void addAll(Ary<? extends Syntax> ss) { if( ss != null ) for( Syntax s : ss ) push(s); }
96  @Override public String toString() { return _ary.toString(); }
97  }
98 
99  // Small classic tree of T2s, immutable, with sharing at the root parts.
100  static class VStack implements Iterable<T2> {
101  final VStack _par;
102  final T2 _nongen;
103  VStack( VStack par, T2 nongen ) { _par=par; _nongen=nongen; }
104  @Override public String toString() { return str(new SB()).toString(); }
105  SB str(SB sb) {
106  _nongen.str(sb,new VBitSet(),new VBitSet());
107  if( _par!=null ) _par.str(sb.p(" >> "));
108  return sb;
109  }
110  @NotNull @Override public Iterator<T2> iterator() { return new Iter(); }
111  private class Iter implements Iterator<T2> {
112  private VStack _vstk;
113  Iter() { _vstk=VStack.this; }
114  @Override public boolean hasNext() { return _vstk!=null; }
115  @Override public T2 next() { T2 v = _vstk._nongen; _vstk = _vstk._par; return v; }
116  }
117  }
118 
119  public static abstract class Syntax {
122  T2 _t; // Current HM type
123  T2 find() { // U-F find
124  T2 t = _t.find();
125  return t==_t ? t : (_t=t);
126  }
127  T2 debug_find() { return _t.find(); } // Find, without the roll-up
128 
129  // Compute and set a new HM type.
130  // If no change, return false.
131  // If a change, return always true, however:
132  // - If 'work' is null do not change/set anything.
133  // - If 'work' is available, set a new HM in '_t' and update the worklist.
134  abstract boolean hm(Worklist work);
135 
136  abstract int prep_tree(Syntax par, VStack nongen, Worklist work);
137  final void prep_tree_impl( Syntax par, VStack nongen, Worklist work, T2 t ) { _par=par; _t=t; _nongen = nongen; work.push(this); }
138  abstract void prep_lookup_deps(Ident id);
139 
140  abstract T2 lookup(String name); // Lookup name in scope & return type; TODO: pre-cache this.
141 
142  abstract void add_kids(Worklist work); // Add children to worklist
143  void add_occurs(Worklist work){}
144 
145  // Giant Assert: True if OK; all Syntaxs off worklist do not make progress
146  abstract boolean more_work(Worklist work);
147  final boolean more_work_impl(Worklist work) {
148  return work.has(this) || !hm(null); // Either on worklist, or no-progress
149  }
150  // Print for debugger
151  @Override final public String toString() { return str(new SB()).toString(); }
152  abstract SB str(SB sb);
153  // Line-by-line print with more detail
154  public String p() { return p0(new SB(), new VBitSet()).toString(); }
155  final SB p0(SB sb, VBitSet dups) {
156  _t.get_dups(dups);
157  _t.str(p1(sb.i()).p(" "), new VBitSet(),dups).nl();
158  return p2(sb.ii(1),dups).di(1);
159  }
160  abstract SB p1(SB sb); // Self short print
161  abstract SB p2(SB sb, VBitSet dups); // Recursion print
162  }
163 
164  public static class Con extends Syntax {
165  final Type _con;
166  Con(Type con) { super(); _con=con; }
167  @Override SB str(SB sb) { return p1(sb); }
168  @Override SB p1(SB sb) { return sb.p(_con instanceof TypeMemPtr ? "str" : _con.toString()); }
169  @Override SB p2(SB sb, VBitSet dups) { return sb; }
170  @Override boolean hm(Worklist work) { assert find().isa("Base"); return false; }
171  @Override T2 lookup(String name) { throw unimpl("should not reach here"); }
172  @Override void add_kids(Worklist work) { }
173  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) { prep_tree_impl(par, nongen, work, T2.make_base(_con)); return 1; }
174  @Override void prep_lookup_deps(Ident id) { throw unimpl("should not reach here"); }
175  @Override boolean more_work(Worklist work) { return more_work_impl(work); }
176  }
177 
178  public static class Ident extends Syntax {
179  final String _name;
180  Ident(String name) { _name=name; }
181  @Override SB str(SB sb) { return p1(sb); }
182  @Override SB p1(SB sb) { return sb.p(_name); }
183  @Override SB p2(SB sb, VBitSet dups) { return sb; }
184  @Override boolean hm(Worklist work) {
185  // A boolean if name is from a Let._body (or PRIM) vs Let._def (or
186  // Lambda). Not helpful, as its only useful at the top-layer.
187  // Structural unification requires the 'occurs check' at each internal
188  // layer, which can differ from the top-layer.
189  //boolean occurs_fresh = _par==null /*from prims*/ || _par.is_fresh(_name,this);
190  T2 t = _par==null ? null : _par.lookup(_name); // Lookup in current env
191  if( t==null ) t = PRIMS.get(_name); // Lookup in prims
192  if( t==null )
193  throw new RuntimeException("Parse error, "+_name+" is undefined");
194  return t.fresh_unify(find(),_nongen,work);
195  }
196  @Override T2 lookup(String name) { throw unimpl("should not reach here"); }
197  @Override void add_kids(Worklist work) { }
198  @Override void add_occurs(Worklist work) {
199  T2 t = _par==null ? null : _par.lookup(_name); // Lookup in current env
200  if( t==null ) t = PRIMS.get(_name); // Lookup in prims
201  if( t.occurs_in(_par) ) // Got captured in some parent?
202  t.add_deps_work(work); // Need to revisit dependent ids
203  }
204  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
205  prep_tree_impl(par,nongen,work,T2.make_leaf());
206  for( Syntax syn = _par; syn!=null; syn = syn._par )
207  syn.prep_lookup_deps(this);
208  return 1;
209  }
210  @Override void prep_lookup_deps(Ident id) { throw unimpl("should not reach here"); }
211  @Override boolean more_work(Worklist work) { return more_work_impl(work); }
212  }
213 
214  public static class Lambda extends Syntax {
215  final String _arg0;
216  final Syntax _body;
218  Lambda(String arg0, Syntax body) { _arg0=arg0; _body=body; _targ = T2.make_leaf(); }
219  @Override SB str(SB sb) { return _body.str(sb.p("{ ").p(_arg0).p(" -> ")).p(" }"); }
220  @Override SB p1(SB sb) { return sb.p("{ ").p(_arg0).p(" -> ... } "); }
221  @Override SB p2(SB sb, VBitSet dups) { return _body.p0(sb,dups); }
222  T2 targ() { T2 targ = _targ.find(); return targ==_targ ? targ : (_targ=targ); }
223  @Override boolean hm(Worklist work) {
224  // The normal lambda work
225  T2 old = find();
226  if( old.is_fun() && // Already a function? Compare-by-parts
227  !old.args(0).unify(targ() ,work) &&
228  !old.args(1).unify(_body.find(),work) )
229  return false;
230  // Make a new T2 for progress
231  T2 fun = T2.make_fun(targ(),_body.find());
232  return old.unify(fun,work);
233  }
234  @Override T2 lookup(String name) {
235  if( Util.eq(_arg0,name) ) return targ();
236  return _par==null ? null : _par.lookup(name);
237  }
238  @Override void add_kids(Worklist work) { work.push(_body); }
239  @Override void add_occurs(Worklist work) {
240  if( targ().occurs_in_type(find()) ) work.addAll(_targ._deps);
241  }
242  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
243  prep_tree_impl(par,nongen,work,T2.make_leaf());
244  return _body.prep_tree(this,new VStack(nongen,_targ),work) + 1;
245  }
246  @Override void prep_lookup_deps(Ident id) {
247  if( Util.eq(id._name,_arg0) ) _targ.push_update(id);
248  }
249  @Override boolean more_work(Worklist work) {
250  if( !more_work_impl(work) ) return false;
251  return _body.more_work(work);
252  }
253  }
254 
255  public static class Lambda2 extends Syntax {
256  final String _arg0, _arg1;
257  final Syntax _body;
260  Lambda2(String arg0, String arg1, Syntax body) { _arg0=arg0; _arg1 = arg1; _body=body; _targ0 = T2.make_leaf(); _targ1 = T2.make_leaf(); }
261  @Override SB str(SB sb) { return _body.str(sb.p("{ ").p(_arg0).p(" ").p(_arg1).p(" -> ")).p(" }"); }
262  @Override SB p1(SB sb) { return sb.p("{ ").p(_arg0).p(" ").p(_arg1).p(" -> ... } "); }
263  @Override SB p2(SB sb, VBitSet dups) { return _body.p0(sb,dups); }
264  T2 targ0() { T2 targ = _targ0.find(); return targ==_targ0 ? targ : (_targ0=targ); }
265  T2 targ1() { T2 targ = _targ1.find(); return targ==_targ1 ? targ : (_targ1=targ); }
266  @Override boolean hm(Worklist work) {
267  // The normal lambda work
268  T2 old = find();
269  if( old.is_fun() && // Already a function? Compare-by-parts
270  !old.args(0).unify(targ0() ,work) &&
271  !old.args(1).unify(targ1() ,work) &&
272  !old.args(2).unify(_body.find(),work) )
273  return false;
274  // Make a new T2 for progress
275  T2 fun = T2.make_fun(targ0(),targ1(),_body.find());
276  return old.unify(fun,work);
277  }
278  @Override T2 lookup(String name) {
279  if( Util.eq(_arg0,name) ) return targ0();
280  if( Util.eq(_arg1,name) ) return targ1();
281  return _par==null ? null : _par.lookup(name);
282  }
283  @Override void add_kids(Worklist work) { work.push(_body); }
284  @Override void add_occurs(Worklist work) {
285  if( targ0().occurs_in_type(find()) ) work.addAll(_targ0._deps);
286  if( targ1().occurs_in_type(find()) ) work.addAll(_targ1._deps);
287  }
288  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
289  prep_tree_impl(par,nongen,work,T2.make_leaf());
290  VStack vs0 = new VStack(nongen,_targ0);
291  VStack vs1 = new VStack(vs0 ,_targ1);
292  return _body.prep_tree(this,vs1,work) + 1;
293  }
294  @Override void prep_lookup_deps(Ident id) {
295  if( Util.eq(id._name,_arg0) ) _targ0.push_update(id);
296  if( Util.eq(id._name,_arg1) ) _targ1.push_update(id);
297  }
298  @Override boolean more_work(Worklist work) {
299  if( !more_work_impl(work) ) return false;
300  return _body.more_work(work);
301  }
302  }
303 
304  public static class Let extends Syntax {
305  final String _arg0;
306  final Syntax _def, _body;
308  Let(String arg0, Syntax def, Syntax body) { _arg0=arg0; _body=body; _def=def; _targ=T2.make_leaf(); }
309  @Override SB str(SB sb) { return _body.str(_def.str(sb.p("let ").p(_arg0).p(" = ")).p(" in ")); }
310  @Override SB p1(SB sb) { return sb.p("let ").p(_arg0).p(" = ... in ..."); }
311  @Override SB p2(SB sb, VBitSet dups) { _body.p0(sb,dups); return _def.p0(sb,dups); }
312  T2 targ() { T2 targ = _targ.find(); return targ==_targ ? targ : (_targ=targ); }
313  @Override boolean hm(Worklist work) {
314  return targ().unify(_def.find(),work);
315  }
316  @Override T2 lookup(String name) {
317  if( Util.eq(_arg0,name) ) return targ();
318  return _par==null ? null : _par.lookup(name);
319  }
320  @Override void add_kids(Worklist work) { work.push(_body); work.push(_def); }
321  @Override void add_occurs(Worklist work) {
322  if( targ().occurs_in_type(find()) ) work.addAll(_targ._deps);
323  }
324  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
325  prep_tree_impl(par,nongen,work,_body._t);
326  int cnt = _body.prep_tree(this, nongen ,work) +
327  _def .prep_tree(this,new VStack(nongen,_targ),work);
328  _t = _body._t; // Unify 'Let._t' with the '_body'
329  return cnt;
330  }
331  @Override void prep_lookup_deps(Ident id) {
332  if( Util.eq(id._name,_arg0) ) _targ.push_update(id);
333  }
334  @Override boolean more_work(Worklist work) {
335  if( !more_work_impl(work) ) return false;
336  return _body.more_work(work) && _def.more_work(work);
337  }
338  }
339 
340  public static class Apply extends Syntax {
341  final Syntax _fun;
342  final Syntax[] _args;
343  Apply(Syntax fun, Syntax... args) { _fun = fun; _args = args; }
344  @Override SB str(SB sb) {
345  _fun.str(sb.p("(")).p(" ");
346  for( Syntax arg : _args )
347  arg.str(sb).p(" ");
348  return sb.unchar().p(")");
349  }
350  @Override SB p1(SB sb) { return sb.p("(...)"); }
351  @Override SB p2(SB sb, VBitSet dups) {
352  _fun.p0(sb,dups);
353  for( Syntax arg : _args ) arg.p0(sb,dups);
354  return sb;
355  }
356 
357  @Override boolean hm(Worklist work) {
358  // Unifiying these: make_fun(this.arg0 this.arg1 -> new )
359  // _fun{_fun.arg0 _fun.arg1 -> _fun.rez}
360  // Progress if:
361  // _fun is not a function
362  // any arg-pair-unifies make progress
363  // this-unify-_fun.return makes progress
364 
365  T2 tfun = _fun.find();
366  if( !tfun.is_fun() ) {
367  if( work==null ) return true; // Will-progress & just-testing
368  T2[] targs = new T2[_args.length+1];
369  for( int i=0; i<_args.length; i++ )
370  targs[i] = _args[i].find();
371  targs[_args.length] = find(); // Return
372  T2 nfun = T2.make_fun(targs);
373  tfun.unify(nfun,work);
374  return true; // Always progress (since forcing tfun to be a fun)
375  }
376 
377  if( tfun._args.length != _args.length+1 )
378  throw new RuntimeException("Mismatched argument lengths");
379  // Check for progress amongst arg pairs
380  boolean progress = false;
381  for( int i=0; i<_args.length; i++ ) {
382  progress |= tfun.args(i).unify(_args[i].find(),work);
383  if( progress && work==null )
384  return true; // Will-progress & just-testing early exit
385  }
386  progress |= tfun.args(_args.length).unify(find(),work);
387  return progress;
388  }
389  @Override T2 lookup(String name) { return _par==null ? null : _par.lookup(name); }
390  @Override void add_kids(Worklist work) { for( Syntax arg : _args ) work.push(arg); }
391  @Override int prep_tree(Syntax par, VStack nongen, Worklist work) {
392  prep_tree_impl(par,nongen,work,T2.make_leaf());
393  int cnt = _fun.prep_tree(this,nongen,work);
394  for( Syntax arg : _args ) cnt += arg.prep_tree(this,nongen,work);
395  return cnt;
396  }
397  @Override void prep_lookup_deps(Ident id) { }
398  @Override boolean more_work(Worklist work) {
399  if( !more_work_impl(work) ) return false;
400  if( !_fun.more_work(work) ) return false;
401  for( Syntax arg : _args ) if( !arg.more_work(work) ) return false;
402  return true;
403  }
404  }
405 
406  // ---------------------------------------------------------------------
407  // T2 types form a Lattice, with 'unify' same as 'meet'. T2's form a DAG
408  // (cycles if i allow recursive unification) with sharing. Each Syntax has a
409  // T2, and the forest of T2s can share. Leaves of a T2 can be either a
410  // simple concrete base type, or a sharable leaf. Unify is structural, and
411  // where not unifyable the union is replaced with an Error.
412  public static class T2 {
413  private static int CNT=0;
414  final int _uid;
415 
416  // A plain type variable starts with a 'V', and can unify directly.
417  // Everything else is structural - during unification they must match names
418  // and arguments and Type constants.
419  final @NotNull String _name; // name, e.g. "->" or "pair" or "V123" or "base"
420 
421  // Structural parts to unify with, or slot 0 is used during normal U-F
422  T2 @NotNull [] _args;
423 
424  // Base types carry a concrete Type
426 
427  // Dependent (non-local) tvars to revisit
429 
430 
431  static T2 make_fun(T2... args) { return new T2("->",null,args); }
432  static T2 make_leaf() { return new T2("V"+CNT,null,new T2[1]); }
433  static T2 make_base(Type con) { return new T2("Base",con); }
434  static T2 prim(String name, T2... args) { return new T2(name,null,args); }
435  T2 copy() { return new T2(_name,_con,new T2[_args.length]); }
436 
437  private T2(@NotNull String name, Type con, T2 @NotNull ... args) {
438  _uid = CNT++;
439  _name= name;
440  _con = con;
441  _args= args;
442  }
443 
444  // A type var, not a concrete leaf. Might be U-Fd or not.
445  boolean is_leaf() { return _name.charAt(0)=='V' || (isa("Base") && _con==null); }
446  boolean no_uf() { return !is_leaf() || _args[0]==null; }
447  boolean isa(String name) { return Util.eq(_name,name); }
448  boolean is_base() { return isa("Base") && _con!=null; }
449  boolean is_fun () { return isa("->"); }
450 
451  // U-F find
452  T2 find() {
453  if( !is_leaf() ) return this; // Shortcut
454  T2 u = _args[0];
455  if( u==null ) return this; // Shortcut
456  if( u.no_uf() ) return u; // Shortcut
457  // U-F fixup
458  while( u.is_leaf() && u._args[0]!=null ) u = u._args[0];
459  T2 v = this, v2;
460  while( !v.is_leaf() && (v2=v._args[0])!=u ) { v._args[0]=u; v = v2; }
461  return u;
462  }
463  // U-F find on the args array
464  T2 args(int i) {
465  T2 u = _args[i];
466  T2 uu = u.find();
467  return u==uu ? uu : (_args[i]=uu);
468  }
469 
470  // U-F union; this becomes that; returns 'that'.
471  // No change if only testing, and reports progress.
472  boolean union(T2 that, Worklist work) {
473  assert is_leaf() && no_uf(); // Cannot union twice
474  if( this==that ) return false;
475  if( work==null ) return true; // Report progress without changing
476  // Worklist: put updates on the worklist for revisiting
477  if( _deps != null ) {
478  work.addAll(_deps); // Re-Apply
479  // Merge update lists, for future unions
480  if( that._deps==null && that.is_leaf() ) that._deps = _deps;
481  else
482  for( Ident dep : _deps ) that.push_update(dep);
483  _deps = null;
484  }
485  _args[0] = that; // U-F update
486  return true;
487  }
488 
489  // Structural unification.
490  // Returns false if no-change, true for change.
491  // If work is null, does not actually change anything, just reports progress.
492  // If work and change, unifies 'this' into 'that' (changing both), and
493  // updates the worklist.
494  static private final HashMap<Long,T2> DUPS = new HashMap<>();
495  boolean unify( T2 that, Worklist work ) {
496  if( this==that ) return false;
497  assert DUPS.isEmpty();
498  boolean progress = _unify(that,work);
499  DUPS.clear();
500  return progress;
501  }
502 
503  // Structural unification, 'this' into 'that'. No change if just testing
504  // (work is null) and returns 'that' if progress. If updating, both 'this'
505  // and 'that' are the same afterwards. Sets PROGRESS.
506  private boolean _unify(T2 that, Worklist work) {
507  assert no_uf() && that.no_uf();
508  if( this==that ) return false;
509 
510  // two leafs union in either order, so keep lower uid
511  if( is_leaf() && that.is_leaf() && _uid<that._uid ) return that.union(this,work);
512  if( is_leaf() ) return union(that,work);
513  if( that.is_leaf() ) return that.union(this,work);
514  if( is_base() && that.is_base() ) return unify_base(that,work);
515 
516  if( !Util.eq(_name,that._name) )
517  throw new RuntimeException("Cannot unify "+this+" and "+that);
518  assert _args!=that._args; // Not expecting to share _args and not 'this'
519  if( _args.length != that._args.length )
520  throw new RuntimeException("Cannot unify "+this+" and "+that);
521 
522  // Cycle check
523  long luid = dbl_uid(that);
524  T2 rez = DUPS.get(luid);
525  assert rez==null || rez==that;
526  if( rez!=null ) return false; // Been there, done that
527  DUPS.put(luid,that); // Close cycles
528 
529  // Structural recursion unification.
530  boolean progress=false;
531  for( int i=0; i<_args.length; i++ ) {
532  progress |= args(i)._unify(that.args(i),work);
533  if( progress && work!=null ) return true;
534  }
535  return progress;
536  }
537 
538  private long dbl_uid(T2 t) { return ((long)_uid<<32)|t._uid; }
539 
540  private boolean unify_base(T2 that, Worklist work) {
541  fresh_base(that,work);
542  if( work==null ) return true;
543  _args = new T2[1]; // Room for a forwarding pointer
544  _con=null; // Flip from 'Base' to 'Leaf'
545  return union(that,work);
546  }
547  private boolean fresh_base(T2 that, Worklist work) {
548  Type con = _con.meet(that._con);
549  if( con==that._con ) return false; // No progress
550  if( work!=null ) that._con = con; // Yes progress, but no update if null work
551  return true;
552  }
553 
554  // Make a (lazy) fresh copy of 'this' and unify it with 'that'. This is
555  // the same as calling 'fresh' then 'unify', without the clone of 'this'.
556  // The Syntax is used when making the 'fresh' copy for the occurs_check;
557  // it is another version of the 'nongen' set.
558  // Returns progress.
559  // If work is null, we are testing only and make no changes.
560  static private final HashMap<T2,T2> VARS = new HashMap<>();
561  boolean fresh_unify(T2 that, VStack nongen, Worklist work) {
562  assert VARS.isEmpty() && DUPS.isEmpty();
563  int old = CNT;
564  boolean progress = _fresh_unify(that,nongen,work);
565  VARS.clear(); DUPS.clear();
566  if( work==null && old!=CNT && DEBUG_LEAKS )
567  throw unimpl("busted, made T2s but just testing");
568  return progress;
569  }
570 
571  // Outer recursive version, wraps a VARS check around other work
572  private boolean _fresh_unify(T2 that, VStack nongen, Worklist work) {
573  assert no_uf() && that.no_uf();
574  T2 prior = VARS.get(this);
575  if( prior!=null ) // Been there, done that
576  return prior.find()._unify(that,work); // Also 'prior' needs unification with 'that'
577  if( cycle_equals(that) ) return vput(that,false);
578 
579  // Attempting to pre-compute occurs_in, by computing 'is_fresh' in the
580  // Ident.hm() call does NOT work. The 'is_fresh' is for the top-layer
581  // only, not the internal layers. As soon as we structural recurse down
582  // a layer, 'is_fresh' does not correlate with an occurs_in check.
583  if( nongen_in(nongen) ) return vput(that,_unify(that,work)); // Famous 'occurs-check', switch to normal unify
584  if( this.is_leaf() ) return vput(that,false); // Lazy map LHS tvar to RHS
585  if( that.is_leaf() ) // RHS is a tvar; union with a deep copy of LHS
586  return work==null || vput(that,that.union(_fresh(nongen),work));
587  // Bases MEET cons in RHS
588  if( is_base() && that.is_base() ) return vput(that,fresh_base(that,work));
589 
590  if( !Util.eq(_name,that._name) ||
591  _args.length != that._args.length )
592  throw new RuntimeException("Cannot unify "+this+" and "+that);
593 
594  // Structural recursion unification, lazy on LHS
595  boolean progress = vput(that,false); // Early set, to stop cycles
596  for( int i=0; i<_args.length; i++ ) {
597  progress |= args(i)._fresh_unify(that.args(i),nongen,work);
598  if( progress && work==null ) return true;
599  }
600  return progress;
601  }
602 
603  private boolean vput(T2 that, boolean progress) { VARS.put(this,that); return progress; }
604 
605  // Return a fresh copy of 'this'
606  private T2 _fresh(VStack nongen) {
607  assert no_uf();
608  T2 rez = VARS.get(this);
609  if( rez!=null ) return rez; // Been there, done that
610 
611  if( is_leaf() ) {
612  // If occurs_in lexical scope, keep same variable, else make a new leaf
613  T2 t = nongen_in(nongen) ? this : T2.make_leaf();
614  VARS.put(this,t);
615  return t;
616  } else { // Structure is deep-replicated
617  T2 t = copy();
618  VARS.put(this,t); // Stop cyclic structure looping
619  for( int i=0; i<_args.length; i++ )
620  t._args[i] = args(i)._fresh(nongen);
621  return t;
622  }
623  }
624 
625  private static final VBitSet ODUPS = new VBitSet();
626  boolean occurs_in(Syntax syn) {
627  if( syn==null ) return false;
628  assert ODUPS.isEmpty();
629  boolean found = _occurs_in(syn);
630  ODUPS.clear();
631  return found;
632  }
633  boolean occurs_in_type(T2 x) {
634  assert ODUPS.isEmpty();
635  boolean found = _occurs_in_type(x);
636  ODUPS.clear();
637  return found;
638  }
639  boolean _occurs_in(Syntax syn) {
640  for( ; syn!=null; syn=syn._par )
641  if( _occurs_in_type(syn.find()) )
642  return true;
643  return false;
644  }
645 
646  boolean _occurs_in_type(T2 x) {
647  assert no_uf() && x.no_uf();
648  if( x==this ) return true;
649  if( ODUPS.tset(x._uid) ) return false; // Been there, done that
650  if( !x.is_leaf() )
651  for( int i=0; i<x._args.length; i++ )
652  if( _occurs_in_type(x.args(i)) )
653  return true;
654  return false;
655  }
656 
657  boolean nongen_in(VStack syn) {
658  if( syn==null ) return false;
659  assert ODUPS.isEmpty();
660  boolean found = _nongen_in(syn);
661  ODUPS.clear();
662  return found;
663  }
664  boolean _nongen_in(VStack nongen) {
665  for( T2 t2 : nongen )
666  if( _occurs_in_type(t2.find()) )
667  return true;
668  return false;
669  }
670 
671  // Test for structural equivalence, including cycles
672  static private final HashMap<T2,T2> CDUPS = new HashMap<>();
673  boolean cycle_equals(T2 t) {
674  assert CDUPS.isEmpty();
675  boolean rez = _cycle_equals(t);
676  CDUPS.clear();
677  return rez;
678  }
679  boolean _cycle_equals(T2 t) {
680  assert no_uf() && t.no_uf();
681  if( this==t ) return true;
682  if( is_base() && t.is_base() )
683  return _con==t._con; // Base-cases have to be completely identical
684  if( !Util.eq(_name,t._name) || // Wrong type-var names
685  _args.length != t._args.length ) // Mismatched sizes
686  return false;
687  if( _args==t._args ) return true;
688  // Cycles stall the equal/unequal decision until we see a difference.
689  T2 tc = CDUPS.get(this);
690  if( tc!=null )
691  return tc==t; // Cycle check; true if both cycling the same
692  CDUPS.put(this,t);
693  for( int i=0; i<_args.length; i++ )
694  if( !args(i)._cycle_equals(t.args(i)) )
695  return false;
696  return true;
697  }
698 
699  // This is a T2 function that is the target of 'fresh', i.e., this function
700  // might be fresh-unified with some other function. Push the application
701  // down the function parts; if any changes the fresh-application may make
702  // progress.
703  static final VBitSet UPDATE_VISIT = new VBitSet();
704  boolean push_update(Ident a) { assert UPDATE_VISIT.isEmpty(); push_update_impl(a); UPDATE_VISIT.clear(); return true; }
705  private void push_update_impl(Ident a) {
706  assert no_uf();
707  if( is_leaf() || _args.length==0 ) {
708  if( _deps==null ) _deps = new Ary<>(Ident.class);
709  if( _deps.find(a)==-1 ) _deps.push(a);
710  } else {
711  if( UPDATE_VISIT.tset(_uid) ) return;
712  for( int i=0; i<_args.length; i++ )
713  args(i).push_update_impl(a);
714  }
715  }
716 
717  void add_deps_work( Worklist work ) { assert UPDATE_VISIT.isEmpty(); add_deps_work_impl(work); UPDATE_VISIT.clear(); }
718  private void add_deps_work_impl( Worklist work ) {
719  if( is_leaf() || _args.length==0 ) {
720  work.addAll(_deps);
721  } else {
722  if( UPDATE_VISIT.tset(_uid) ) return;
723  for( int i=0; i<_args.length; i++ )
724  args(i).add_deps_work_impl(work);
725  }
726  }
727 
728  // -----------------
729  // Glorious Printing
730 
731  // Look for dups, in a tree or even a forest (which Syntax.p() does)
732  VBitSet get_dups(VBitSet dups) { return _get_dups(new VBitSet(),dups); }
734  if( visit.tset(_uid) && no_uf() ) dups.set(_uid);
735  else
736  for( T2 t : _args )
737  if( t!=null )
738  t._get_dups(visit,dups);
739  return dups;
740  }
741 
742  // Fancy print for Debuggers - includes explicit U-F re-direction.
743  // Does NOT roll-up U-F, has no side-effects.
744  @Override public String toString() { return str(new SB(), new VBitSet(), get_dups(new VBitSet()) ).toString(); }
745  SB str(SB sb, VBitSet visit, VBitSet dups) {
746  if( is_leaf() || is_base() ) {
747  if( is_base() ) sb.p(_con instanceof TypeMemPtr ? "str" : _con.toString()); else sb.p(_name);
748  return _args.length==0 || _args[0]==null ? sb : _args[0].str(sb.p(">>"), visit, dups);
749  }
750  boolean dup = dups.get(_uid);
751  if( dup ) sb.p('$').p(_uid);
752  if( visit.tset(_uid) && dup ) return sb;
753  if( dup ) sb.p(':');
754 
755  if( is_fun() ) {
756  sb.p("{ ");
757  for( int i=0; i<_args.length-1; i++ )
758  str(sb,visit,_args[i],dups).p(" ");
759  return str(sb.p("-> "),visit,_args[_args.length-1],dups).p(" }");
760  }
761  // Generic structural T2
762  sb.p("(").p(_name).p(" ");
763  for( T2 t : _args ) str(sb,visit,t,dups).p(" ");
764  return sb.unchar().p(")");
765  }
766  static private SB str(SB sb, VBitSet visit, T2 t, VBitSet dups) { return t==null ? sb.p("_") : t.str(sb,visit,dups); }
767 
768  // Same as toString but calls find(). Can thus side-effect & roll-up U-Fs, so not a toString
769  public String p() { return p(get_dups(new VBitSet())); }
770  String p(VBitSet dups) { return find()._p(new SB(), new VBitSet(), dups).toString(); }
771  private SB _p(SB sb, VBitSet visit, VBitSet dups) {
772  assert no_uf();
773  if( is_base() ) return sb.p(_con instanceof TypeMemPtr ? "str" : _con.toString() );
774  if( is_leaf() ) return sb.p(_name);
775  boolean dup = dups.get(_uid);
776  if( dup ) sb.p('$').p(_uid);
777  if( visit.tset(_uid) && dup ) return sb;
778  if( dup ) sb.p(':');
779  if( is_fun() ) {
780  sb.p("{ ");
781  for( int i=0; i<_args.length-1; i++ )
782  args(i)._p(sb,visit,dups).p(" ");
783  return args(_args.length-1)._p(sb.p("-> "),visit,dups).p(" }");
784  }
785  // Generic structural T2
786  sb.p("(").p(_name).p(" ");
787  for( int i=0; i<_args.length; i++ ) args(i)._p(sb,visit,dups).p(" ");
788  return sb.unchar().p(")");
789  }
790 
791  static void reset() { CNT=0; DUPS.clear(); VARS.clear(); ODUPS.clear(); CDUPS.clear(); UPDATE_VISIT.clear(); }
792  }
793 
794 }
com.cliffc.aa.HM.HM5.Lambda2.targ0
T2 targ0()
Definition: HM5.java:264
com.cliffc.aa.HM.HM5.Ident.lookup
T2 lookup(String name)
Definition: HM5.java:196
com.cliffc.aa.HM.HM5.Lambda2.add_kids
void add_kids(Worklist work)
Definition: HM5.java:283
com.cliffc.aa.HM.HM5.T2.CDUPS
static final HashMap< T2, T2 > CDUPS
Definition: HM5.java:672
com.cliffc.aa.HM.HM5.T2.VARS
static final HashMap< T2, T2 > VARS
Definition: HM5.java:560
com.cliffc.aa.HM.HM5.T2._occurs_in_type
boolean _occurs_in_type(T2 x)
Definition: HM5.java:646
com.cliffc.aa.HM.HM5.Let.Let
Let(String arg0, Syntax def, Syntax body)
Definition: HM5.java:308
com.cliffc.aa.HM.HM5.Let._targ
T2 _targ
Definition: HM5.java:307
com.cliffc.aa.HM.HM5.T2._get_dups
VBitSet _get_dups(VBitSet visit, VBitSet dups)
Definition: HM5.java:733
com.cliffc.aa.HM.HM5.Let.add_occurs
void add_occurs(Worklist work)
Definition: HM5.java:321
com.cliffc.aa.HM.HM5.VStack.VStack
VStack(VStack par, T2 nongen)
Definition: HM5.java:103
com.cliffc.aa.HM.HM5.Con.add_kids
void add_kids(Worklist work)
Definition: HM5.java:172
com.cliffc.aa.HM.HM5.Con.more_work
boolean more_work(Worklist work)
Definition: HM5.java:175
com.cliffc.aa.HM.HM5.Ident.more_work
boolean more_work(Worklist work)
Definition: HM5.java:211
com.cliffc.aa.HM.HM5.VStack.Iter._vstk
VStack _vstk
Definition: HM5.java:112
com.cliffc.aa.HM.HM5.T2._name
final String _name
Definition: HM5.java:419
com.cliffc.aa.HM.HM5.T2.UPDATE_VISIT
static final VBitSet UPDATE_VISIT
Definition: HM5.java:703
com.cliffc.aa.HM.HM5.T2.make_base
static T2 make_base(Type con)
Definition: HM5.java:433
com.cliffc.aa.HM.HM5.Let.p2
SB p2(SB sb, VBitSet dups)
Definition: HM5.java:311
com.cliffc.aa.HM.HM5.Ident.Ident
Ident(String name)
Definition: HM5.java:180
com.cliffc.aa.HM.HM5.Let.lookup
T2 lookup(String name)
Definition: HM5.java:316
com.cliffc.aa.HM.HM5.Apply
Definition: HM5.java:340
com.cliffc.aa.HM.HM5.Con.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM5.java:174
com.cliffc.aa.HM.HM5.Con.Con
Con(Type con)
Definition: HM5.java:166
com.cliffc.aa.HM.HM5.Con._con
final Type _con
Definition: HM5.java:165
com.cliffc.aa.HM.HM5.PRIMS
static final HashMap< String, T2 > PRIMS
Definition: HM5.java:24
com.cliffc.aa.util.Util.eq
static boolean eq(String s0, String s1)
Definition: Util.java:16
com.cliffc.aa.HM.HM5.T2._fresh_unify
boolean _fresh_unify(T2 that, VStack nongen, Worklist work)
Definition: HM5.java:572
com.cliffc.aa.util.SB.ii
SB ii(int i)
Definition: SB.java:44
com.cliffc.aa.HM.HM5.T2.nongen_in
boolean nongen_in(VStack syn)
Definition: HM5.java:657
com.cliffc
com.cliffc.aa.type.Type.toString
final String toString()
Definition: Type.java:127
com.cliffc.aa.util.SB.di
SB di(int i)
Definition: SB.java:46
com.cliffc.aa.HM.HM5.T2.DUPS
static final HashMap< Long, T2 > DUPS
Definition: HM5.java:494
com.cliffc.aa.HM.HM5.Ident.p1
SB p1(SB sb)
Definition: HM5.java:182
com.cliffc.aa.HM.HM5.Lambda2.str
SB str(SB sb)
Definition: HM5.java:261
com.cliffc.aa.HM.HM5.Worklist._ary
final Ary< Syntax > _ary
Definition: HM5.java:88
com.cliffc.aa.HM.HM5.Ident.add_kids
void add_kids(Worklist work)
Definition: HM5.java:197
com.cliffc.aa.HM.HM5.Syntax.p
String p()
Definition: HM5.java:154
com.cliffc.aa.HM.HM5.Apply.str
SB str(SB sb)
Definition: HM5.java:344
com.cliffc.aa.HM.HM5.T2._unify
boolean _unify(T2 that, Worklist work)
Definition: HM5.java:506
com.cliffc.aa.HM.HM5.Worklist.pop
Syntax pop()
Definition: HM5.java:93
com.cliffc.aa.HM.HM5.Lambda2
Definition: HM5.java:255
com.cliffc.aa.HM.HM5.Apply.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM5.java:397
com.cliffc.aa.HM.HM5.T2.str
SB str(SB sb, VBitSet visit, VBitSet dups)
Definition: HM5.java:745
com.cliffc.aa.util
Definition: AbstractEntry.java:1
com.cliffc.aa.HM.HM5.Ident.p2
SB p2(SB sb, VBitSet dups)
Definition: HM5.java:183
com.cliffc.aa.HM.HM5.VStack.Iter.next
T2 next()
Definition: HM5.java:115
com.cliffc.aa.HM.HM5.Lambda.p2
SB p2(SB sb, VBitSet dups)
Definition: HM5.java:221
com.cliffc.aa.type.TypeInt
Definition: TypeInt.java:9
com.cliffc.aa.HM.HM5.Con
Definition: HM5.java:164
com.cliffc.aa.HM.HM5.Apply._args
final Syntax[] _args
Definition: HM5.java:342
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.HM.HM5.Lambda2.Lambda2
Lambda2(String arg0, String arg1, Syntax body)
Definition: HM5.java:260
com.cliffc.aa.HM.HM5.Ident.add_occurs
void add_occurs(Worklist work)
Definition: HM5.java:198
com.cliffc.aa.type.TypeFlt
Definition: TypeFlt.java:9
com.cliffc.aa.HM.HM5.T2.args
T2 args(int i)
Definition: HM5.java:464
com.cliffc.aa.util.Ary
Definition: Ary.java:11
com.cliffc.aa.HM.HM5.Syntax.hm
abstract boolean hm(Worklist work)
com.cliffc.aa.HM.HM5.Let.hm
boolean hm(Worklist work)
Definition: HM5.java:313
com.cliffc.aa.HM.HM5.reset
static void reset()
Definition: HM5.java:83
com.cliffc.aa.HM.HM5.Lambda.targ
T2 targ()
Definition: HM5.java:222
com.cliffc.aa.HM.HM5.T2.copy
T2 copy()
Definition: HM5.java:435
com.cliffc.aa.HM.HM5.T2.str
static SB str(SB sb, VBitSet visit, T2 t, VBitSet dups)
Definition: HM5.java:766
com.cliffc.aa.HM.HM5.Apply.add_kids
void add_kids(Worklist work)
Definition: HM5.java:390
com.cliffc.aa.HM.HM5.Worklist.addAll
void addAll(Ary<? extends Syntax > ss)
Definition: HM5.java:95
com.cliffc.aa.HM.HM5.Con.hm
boolean hm(Worklist work)
Definition: HM5.java:170
com.cliffc.aa.HM.HM5.VStack.toString
String toString()
Definition: HM5.java:104
com.cliffc.aa.HM.HM5.VStack.Iter
Definition: HM5.java:111
com.cliffc.aa.HM.HM5.T2.is_fun
boolean is_fun()
Definition: HM5.java:449
com.cliffc.aa.HM.HM5.T2.find
T2 find()
Definition: HM5.java:452
com.cliffc.aa.HM.HM5.T2._deps
Ary< Ident > _deps
Definition: HM5.java:428
com.cliffc.aa.HM.HM5.Lambda2.hm
boolean hm(Worklist work)
Definition: HM5.java:266
com.cliffc.aa.HM.HM5.T2._occurs_in
boolean _occurs_in(Syntax syn)
Definition: HM5.java:639
com.cliffc.aa.HM.HM5.T2.is_base
boolean is_base()
Definition: HM5.java:448
com.cliffc.aa.HM.HM5.Let._def
final Syntax _def
Definition: HM5.java:306
com.cliffc.aa.HM.HM5.T2.make_leaf
static T2 make_leaf()
Definition: HM5.java:432
com.cliffc.aa.HM.HM5.T2._cycle_equals
boolean _cycle_equals(T2 t)
Definition: HM5.java:679
com.cliffc.aa.HM.HM5.Syntax.debug_find
T2 debug_find()
Definition: HM5.java:127
com.cliffc.aa.type.Type.meet
final Type meet(Type t)
Definition: Type.java:412
com.cliffc.aa.HM.HM5.Worklist.toString
String toString()
Definition: HM5.java:96
com.cliffc.aa.HM.HM5.Syntax.prep_tree
abstract int prep_tree(Syntax par, VStack nongen, Worklist work)
com.cliffc.aa.AA.unimpl
static RuntimeException unimpl()
Definition: AA.java:10
com.cliffc.aa.HM.HM5.Lambda2.add_occurs
void add_occurs(Worklist work)
Definition: HM5.java:284
com.cliffc.aa.HM.HM5.Lambda.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM5.java:242
com.cliffc.aa.HM.HM5.T2._uid
final int _uid
Definition: HM5.java:414
com.cliffc.aa.HM.HM5.Con.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM5.java:173
com.cliffc.aa.HM.HM5.Syntax.toString
final String toString()
Definition: HM5.java:151
com.cliffc.aa.HM.HM5.T2.add_deps_work
void add_deps_work(Worklist work)
Definition: HM5.java:717
com.cliffc.aa.util.SB.unchar
SB unchar()
Definition: SB.java:58
Iterable
com.cliffc.aa.HM.HM5.Lambda2._body
final Syntax _body
Definition: HM5.java:257
com.cliffc.aa.HM.HM5.Lambda.lookup
T2 lookup(String name)
Definition: HM5.java:234
com.cliffc.aa.HM.HM5.T2.reset
static void reset()
Definition: HM5.java:791
com.cliffc.aa.util.VBitSet.tset
boolean tset(int idx)
Definition: VBitSet.java:7
com.cliffc.aa.HM.HM5.VStack.Iter.hasNext
boolean hasNext()
Definition: HM5.java:114
com.cliffc.aa.HM.HM5.Apply.Apply
Apply(Syntax fun, Syntax... args)
Definition: HM5.java:343
com.cliffc.aa.HM.HM5.T2.occurs_in_type
boolean occurs_in_type(T2 x)
Definition: HM5.java:633
com.cliffc.aa.HM.HM5.Lambda._targ
T2 _targ
Definition: HM5.java:217
com.cliffc.aa.type.TypeInt.INT64
static final TypeInt INT64
Definition: TypeInt.java:39
com.cliffc.aa.HM.HM5.Lambda.more_work
boolean more_work(Worklist work)
Definition: HM5.java:249
com.cliffc.aa.HM.HM5.Lambda2.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM5.java:294
com.cliffc.aa.HM.HM5.Lambda2._targ1
T2 _targ1
Definition: HM5.java:259
com.cliffc.aa.HM.HM5.T2.get_dups
VBitSet get_dups(VBitSet dups)
Definition: HM5.java:732
com.cliffc.aa.HM.HM5.Ident.str
SB str(SB sb)
Definition: HM5.java:181
com.cliffc.aa.HM.HM5.Apply.p1
SB p1(SB sb)
Definition: HM5.java:350
com.cliffc.aa.HM.HM5.T2.p
String p(VBitSet dups)
Definition: HM5.java:770
com.cliffc.aa.HM.HM5.T2.push_update_impl
void push_update_impl(Ident a)
Definition: HM5.java:705
com.cliffc.aa.HM.HM5.Syntax.p0
final SB p0(SB sb, VBitSet dups)
Definition: HM5.java:155
com.cliffc.aa.HM.HM5.Syntax.lookup
abstract T2 lookup(String name)
com.cliffc.aa.HM.HM5.Let.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM5.java:324
com.cliffc.aa.HM.HM5.T2.union
boolean union(T2 that, Worklist work)
Definition: HM5.java:472
com.cliffc.aa.HM.HM5.Lambda
Definition: HM5.java:214
com.cliffc.aa.HM.HM5.DEBUG_LEAKS
static boolean DEBUG_LEAKS
Definition: HM5.java:25
com.cliffc.aa.HM.HM5.Con.lookup
T2 lookup(String name)
Definition: HM5.java:171
com.cliffc.aa.HM.HM5.Lambda.Lambda
Lambda(String arg0, Syntax body)
Definition: HM5.java:218
com.cliffc.aa.HM.HM5.Ident.hm
boolean hm(Worklist work)
Definition: HM5.java:184
com.cliffc.aa.HM.HM5.T2.push_update
boolean push_update(Ident a)
Definition: HM5.java:704
com.cliffc.aa.HM.HM5.Lambda.str
SB str(SB sb)
Definition: HM5.java:219
com.cliffc.aa.util.Util
Definition: Util.java:5
com.cliffc.aa.HM.HM5.Worklist.len
int len()
Definition: HM5.java:90
com.cliffc.aa.HM.HM5.Lambda._arg0
final String _arg0
Definition: HM5.java:215
com.cliffc.aa.HM.HM5.T2
Definition: HM5.java:412
com.cliffc.aa.HM.HM5.Apply.hm
boolean hm(Worklist work)
Definition: HM5.java:357
com.cliffc.aa.HM.HM5.T2.make_fun
static T2 make_fun(T2... args)
Definition: HM5.java:431
com.cliffc.aa.HM.HM5.T2._nongen_in
boolean _nongen_in(VStack nongen)
Definition: HM5.java:664
com.cliffc.aa.HM.HM5.VStack.iterator
Iterator< T2 > iterator()
Definition: HM5.java:110
com.cliffc.aa.HM.HM5.Syntax.find
T2 find()
Definition: HM5.java:123
com.cliffc.aa.HM.HM5.Lambda.add_occurs
void add_occurs(Worklist work)
Definition: HM5.java:239
com.cliffc.aa.HM.HM5.Apply.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM5.java:391
com.cliffc.aa.HM.HM5.Syntax.add_kids
abstract void add_kids(Worklist work)
com.cliffc.aa.HM.HM5.T2.add_deps_work_impl
void add_deps_work_impl(Worklist work)
Definition: HM5.java:718
com.cliffc.aa.HM.HM5.Lambda2._targ0
T2 _targ0
Definition: HM5.java:258
com.cliffc.aa.HM.HM5.Lambda.p1
SB p1(SB sb)
Definition: HM5.java:220
com.cliffc.aa.HM.HM5.Syntax._t
T2 _t
Definition: HM5.java:122
com.cliffc.aa.HM.HM5.T2.dbl_uid
long dbl_uid(T2 t)
Definition: HM5.java:538
com.cliffc.aa.HM.HM5.Con.p2
SB p2(SB sb, VBitSet dups)
Definition: HM5.java:169
com.cliffc.aa.HM.HM5.Lambda.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM5.java:246
com.cliffc.aa.HM.HM5
Definition: HM5.java:23
com.cliffc.aa.HM.HM5.Syntax._nongen
VStack _nongen
Definition: HM5.java:121
com.cliffc.aa.HM.HM5.Let.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM5.java:331
com.cliffc.aa.HM.HM5.Let._body
final Syntax _body
Definition: HM5.java:306
com.cliffc.aa.HM.HM5.Let
Definition: HM5.java:304
com.cliffc.aa.HM.HM5.Let.str
SB str(SB sb)
Definition: HM5.java:309
com.cliffc.aa.HM.HM5.VStack.Iter.Iter
Iter()
Definition: HM5.java:113
com.cliffc.aa.HM.HM5.T2.CNT
static int CNT
Definition: HM5.java:413
com.cliffc.aa.HM.HM5.Let.more_work
boolean more_work(Worklist work)
Definition: HM5.java:334
com.cliffc.aa.HM.HM5.Syntax.p1
abstract SB p1(SB sb)
com.cliffc.aa.HM.HM5.Lambda.add_kids
void add_kids(Worklist work)
Definition: HM5.java:238
com.cliffc.aa.HM.HM5.Ident
Definition: HM5.java:178
com.cliffc.aa.util.VBitSet
Definition: VBitSet.java:5
com.cliffc.aa.HM.HM5.Syntax.p2
abstract SB p2(SB sb, VBitSet dups)
com.cliffc.aa.HM.HM5.Ident._name
final String _name
Definition: HM5.java:179
com.cliffc.aa.HM.HM5.VStack._nongen
final T2 _nongen
Definition: HM5.java:102
com.cliffc.aa.HM.HM5.VStack._par
final VStack _par
Definition: HM5.java:101
NotNull
com.cliffc.aa.HM.HM5.Syntax.prep_lookup_deps
abstract void prep_lookup_deps(Ident id)
com.cliffc.aa.util.SB
Tight/tiny StringBuilder wrapper.
Definition: SB.java:8
com.cliffc.aa.HM.HM5.Syntax.more_work
abstract boolean more_work(Worklist work)
com.cliffc.aa.HM.HM5.Worklist._work
final HashSet< Syntax > _work
Definition: HM5.java:89
com.cliffc.aa.HM.HM5.Worklist.push
void push(Syntax s)
Definition: HM5.java:91
com.cliffc.aa.HM.HM5.T2.prim
static T2 prim(String name, T2... args)
Definition: HM5.java:434
com.cliffc.aa.HM.HM5.Apply.p2
SB p2(SB sb, VBitSet dups)
Definition: HM5.java:351
com.cliffc.aa.HM.HM5.Lambda2.more_work
boolean more_work(Worklist work)
Definition: HM5.java:298
com.cliffc.aa.AA
an implementation of language AA
Definition: AA.java:9
com.cliffc.aa.HM.HM5.Syntax
Definition: HM5.java:119
com.cliffc.aa.HM.HM5.VStack.str
SB str(SB sb)
Definition: HM5.java:105
com.cliffc.aa.HM.HM5.Lambda2._arg0
final String _arg0
Definition: HM5.java:256
com.cliffc.aa.HM.HM5.T2._fresh
T2 _fresh(VStack nongen)
Definition: HM5.java:606
com.cliffc.aa.HM.HM5.Lambda.hm
boolean hm(Worklist work)
Definition: HM5.java:223
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.HM.HM5.Lambda2.p1
SB p1(SB sb)
Definition: HM5.java:262
com.cliffc.aa.util.SB.nl
SB nl()
Definition: SB.java:48
com.cliffc.aa.HM.HM5.hm
static T2 hm(Syntax prog)
Definition: HM5.java:27
com.cliffc.aa.HM.HM5.Worklist._cnt
int _cnt
Definition: HM5.java:87
com.cliffc.aa.HM.HM5.Lambda2.targ1
T2 targ1()
Definition: HM5.java:265
com.cliffc.aa.HM.HM5.T2.cycle_equals
boolean cycle_equals(T2 t)
Definition: HM5.java:673
com.cliffc.aa.HM.HM5.T2.toString
String toString()
Definition: HM5.java:744
com.cliffc.aa.HM.HM5.Apply.lookup
T2 lookup(String name)
Definition: HM5.java:389
com.cliffc.aa.HM.HM5.Lambda2.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM5.java:288
com.cliffc.aa.util.SB.p
SB p(String s)
Definition: SB.java:13
com.cliffc.aa.HM.HM5.T2._con
Type _con
Definition: HM5.java:425
com.cliffc.aa.HM.HM5.Syntax.add_occurs
void add_occurs(Worklist work)
Definition: HM5.java:143
com.cliffc.aa.HM.HM5.T2.no_uf
boolean no_uf()
Definition: HM5.java:446
com.cliffc.aa.HM.HM5.T2._p
SB _p(SB sb, VBitSet visit, VBitSet dups)
Definition: HM5.java:771
com.cliffc.aa.HM.HM5.Ident.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM5.java:204
com.cliffc.aa.HM.HM5.T2._args
T2[] _args
Definition: HM5.java:422
com.cliffc.aa.HM.HM5.Syntax.str
abstract SB str(SB sb)
com.cliffc.aa.HM.HM5.T2.fresh_base
boolean fresh_base(T2 that, Worklist work)
Definition: HM5.java:547
com.cliffc.aa.HM.HM5.T2.is_leaf
boolean is_leaf()
Definition: HM5.java:445
com.cliffc.aa.HM.HM5.Let.add_kids
void add_kids(Worklist work)
Definition: HM5.java:320
com.cliffc.aa.HM.HM5.Ident.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM5.java:210
com.cliffc.aa.HM.HM5.T2.fresh_unify
boolean fresh_unify(T2 that, VStack nongen, Worklist work)
Definition: HM5.java:561
com.cliffc.aa.HM.HM5.T2.vput
boolean vput(T2 that, boolean progress)
Definition: HM5.java:603
com.cliffc.aa.HM.HM5.T2.ODUPS
static final VBitSet ODUPS
Definition: HM5.java:625
com.cliffc.aa.HM.HM5.T2.occurs_in
boolean occurs_in(Syntax syn)
Definition: HM5.java:626
com.cliffc.aa.HM.HM5.Lambda2.p2
SB p2(SB sb, VBitSet dups)
Definition: HM5.java:263
com.cliffc.aa.HM.HM5.Lambda2._arg1
final String _arg1
Definition: HM5.java:256
com.cliffc.aa.HM.HM5.Apply.more_work
boolean more_work(Worklist work)
Definition: HM5.java:398
com.cliffc.aa.util.SB.i
SB i(int d)
Definition: SB.java:38
com.cliffc.aa.HM.HM5.VStack
Definition: HM5.java:100
com.cliffc.aa.HM.HM5.T2.unify
boolean unify(T2 that, Worklist work)
Definition: HM5.java:495
com.cliffc.aa.type.TypeMemPtr.STRPTR
static final TypeMemPtr STRPTR
Definition: TypeMemPtr.java:97
com.cliffc.aa.HM.HM5.T2.unify_base
boolean unify_base(T2 that, Worklist work)
Definition: HM5.java:540
com.cliffc.aa.HM.HM5.T2.p
String p()
Definition: HM5.java:769
com.cliffc.aa.HM.HM5.T2.isa
boolean isa(String name)
Definition: HM5.java:447
com.cliffc.aa.HM.HM5.Let._arg0
final String _arg0
Definition: HM5.java:305
com.cliffc.aa.HM.HM5.Con.str
SB str(SB sb)
Definition: HM5.java:167
com
com.cliffc.aa.HM.HM5.Apply._fun
final Syntax _fun
Definition: HM5.java:341
com.cliffc.aa.HM.HM5.Lambda2.lookup
T2 lookup(String name)
Definition: HM5.java:278
com.cliffc.aa.HM.HM5.Lambda._body
final Syntax _body
Definition: HM5.java:216
com.cliffc.aa.HM.HM5.Let.targ
T2 targ()
Definition: HM5.java:312
com.cliffc.aa.HM.HM5.Let.p1
SB p1(SB sb)
Definition: HM5.java:310
com.cliffc.aa.type.TypeInt.BOOL
static final TypeInt BOOL
Definition: TypeInt.java:43
com.cliffc.aa.util.SB.toString
String toString()
Definition: SB.java:62
com.cliffc.aa.HM.HM5.Syntax.more_work_impl
final boolean more_work_impl(Worklist work)
Definition: HM5.java:147
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.HM.HM5.Syntax._par
Syntax _par
Definition: HM5.java:120
com.cliffc.aa.HM.HM5.Con.p1
SB p1(SB sb)
Definition: HM5.java:168
com.cliffc.aa.HM.HM5.T2.T2
T2(@NotNull String name, Type con, T2 @NotNull ... args)
Definition: HM5.java:437
com.cliffc.aa.type.TypeFlt.FLT64
static final TypeFlt FLT64
Definition: TypeFlt.java:38
com.cliffc.aa.HM.HM5.Syntax.prep_tree_impl
final void prep_tree_impl(Syntax par, VStack nongen, Worklist work, T2 t)
Definition: HM5.java:137
com.cliffc.aa.HM.HM5.Worklist
Definition: HM5.java:86
com.cliffc.aa.HM.HM5.Worklist.has
boolean has(Syntax s)
Definition: HM5.java:94