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