aa
HM7.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 // Extend to records.
22 
23 public class HM7 {
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  PRIMS.put("nil",T2.make_nil());
38 
39  T2 var1 = T2.make_leaf();
40  T2 var2 = T2.make_leaf();
41  T2 var3 = T2.make_leaf();
42 
43  PRIMS.put("pair1",T2.make_fun(var1, T2.make_fun(var2, T2.prim("pair",var1,var2) ))); // curried
44  PRIMS.put("pair",T2.make_fun(var1, var2, T2.prim("pair",var1,var2) ));
45  PRIMS.put("triple",T2.make_fun(var1, var2, var3, T2.prim("triple",var1,var2,var3) ));
46 
47  PRIMS.put("if",T2.make_fun(var2,var1,var1,var1));
48 
49  PRIMS.put("dec",T2.make_fun(int64,int64));
50  PRIMS.put("*" ,T2.make_fun(int64,int64,int64));
51  PRIMS.put("?0",T2.make_fun(T2.make_leaf(),bool));
52  PRIMS.put("isempty",T2.make_fun(strp,bool));
53 
54  // Print a string; int->str
55  PRIMS.put("str",T2.make_fun(int64,strp));
56  // Factor; FP div/mod-like operation
57  PRIMS.put("factor",T2.make_fun(flt64,T2.prim("divmod",flt64,flt64)));
58 
59  // Parse
60  Syntax prog = parse( sprog );
61 
62  // Prep for SSA: pre-gather all the (unique) ids
63  int DEBUG_CNT=-1;
64  int cnt_syns = prog.prep_tree(null,null,work);
65  int init_T2s = T2.CNT;
66 
67  while( work.len()>0 ) { // While work
68  int oldcnt = T2.CNT; // Used for cost-check when no-progress
69  Syntax syn = work.pop(); // Get work
70  T2 old = syn._t; // Old value for progress assert
71  if( work._cnt==DEBUG_CNT )
72  System.out.println("break here");
73  if( syn.hm(work) ) { // Compute a new HM type and check for progress
74  assert !syn.debug_find().unify(old.find(),null);// monotonic: unifying with the result is no-progress
75  syn.add_kids(work); // Push children on worklist
76  syn.add_occurs(work); // Push occurs-check ids on worklist
77  if( syn._par !=null ) work.push(syn._par); // Parent updates
78  } else {
79  assert !DEBUG_LEAKS || oldcnt==T2.CNT; // No-progress consumes no-new-T2s
80  }
81  // VERY EXPENSIVE ASSERT: O(n^2). Every Syntax that makes progress is on the worklist
82  //assert prog.more_work(work);
83  }
84  assert prog.more_work(work);
85 
86  //System.out.println("Initial T2s: "+init_T2s+", Prog size: "+cnt_syns+", worklist iters: "+work._cnt+", T2s: "+T2.CNT);
87  return prog._t;
88  }
89  static void reset() { PRIMS.clear(); T2.reset(); }
90 
91  // ---------------------------------------------------------------------
92  // Program text for parsing
93  private static int X;
94  private static byte[] BUF;
95  @Override public String toString() { return new String(BUF,X,BUF.length-X); }
96  static Syntax parse( String s ) {
97  X = 0;
98  BUF = s.getBytes();
99  Syntax prog = term();
100  if( skipWS() != -1 ) throw unimpl("Junk at end of program: "+new String(BUF,X,BUF.length-X));
101  return prog;
102  }
103  static Syntax term() {
104  if( skipWS()==-1 ) return null;
105  if( isDigit(BUF[X]) ) return number();
106  if( BUF[X]=='"' ) return string();
107  if( BUF[X]=='(' ) { // Parse an Apply
108  X++; // Skip paren
109  Syntax fun = term();
110  Ary<Syntax> ARGS = new Ary<>(new Syntax[1],0);
111  while( skipWS()!= ')' && X<BUF.length ) ARGS.push(term());
112  return new Apply(fun,require(')',ARGS.asAry()));
113  }
114  if( BUF[X]=='{' ) { // Lambda of 1 or 2 args
115  X++; // Skip paren
116  Ary<String> args = new Ary<>(new String[1],0);
117  while( skipWS()!='-' ) args.push(id());
118  require("->");
119  Syntax body = require('}',term());
120  return new Lambda(body,args.asAry());
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  // Structure
133  if( BUF[X]=='@' ) {
134  X++;
135  require('{',null);
136  Ary<String> ids = new Ary<>(String.class);
137  Ary<Syntax> flds = new Ary<>(Syntax.class);
138  while( skipWS()!='}' && X < BUF.length ) {
139  String id = require('=',id());
140  Syntax fld = term();
141  if( fld==null ) throw unimpl("Missing term for field "+id);
142  ids .push( id);
143  flds.push(fld);
144  if( skipWS()==',' ) X++;
145  }
146  return require('}',new Struct(ids.asAry(),flds.asAry()));
147  }
148 
149  // Field lookup is prefix or backwards: ".x term"
150  if( BUF[X]=='.' ) {
151  X++;
152  return new Field(id(),term());
153  }
154 
155  throw unimpl("Unknown syntax");
156  }
157  private static final SB ID = new SB();
158  private static String id() {
159  ID.clear();
160  while( X<BUF.length && isAlpha1(BUF[X]) )
161  ID.p((char)BUF[X++]);
162  String s = ID.toString().intern();
163  if( s.length()==0 ) throw unimpl("Missing id");
164  return s;
165  }
166  private static Syntax number() {
167  int sum=0;
168  while( X<BUF.length && isDigit(BUF[X]) )
169  sum = sum*10+BUF[X++]-'0';
170  if( X>= BUF.length || BUF[X]!='.' ) return new Con(TypeInt.con(sum));
171  X++;
172  float f = (float)sum;
173  f = f + (BUF[X++]-'0')/10.0f;
174  return new Con(TypeFlt.con(f));
175  }
176  private static Syntax string() {
177  int start = ++X;
178  while( X<BUF.length && BUF[X]!='"' ) X++;
179  return require('"', new Con(TypeStr.con(new String(BUF,start,X-start).intern())));
180  }
181  private static byte skipWS() {
182  while( X<BUF.length && isWS(BUF[X]) ) X++;
183  return X==BUF.length ? -1 : BUF[X];
184  }
185  private static boolean isWS (byte c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; }
186  private static boolean isDigit (byte c) { return '0' <= c && c <= '9'; }
187  private static boolean isAlpha0(byte c) { return ('a'<=c && c <= 'z') || ('A'<=c && c <= 'Z') || (c=='_') || (c=='*') || (c=='?'); }
188  private static boolean isAlpha1(byte c) { return isAlpha0(c) || ('0'<=c && c <= '9') || (c=='/'); }
189  private static <T> T require(char c, T t) { if( skipWS()!=c ) throw unimpl("Missing '"+c+"'"); X++; return t; }
190  private static void require(String s) {
191  skipWS();
192  for( int i=0; i<s.length(); i++ )
193  if( X+i >= BUF.length || BUF[X+i]!=s.charAt(i) )
194  throw unimpl("Missing '"+s+"'");
195  X+=s.length();
196  }
197 
198  // ---------------------------------------------------------------------
199  // Worklist of Syntax nodes
200  private static class Worklist {
201  public int _cnt;
202  private final Ary<Syntax> _ary = new Ary<>(Syntax.class); // For picking random element
203  private final HashSet<Syntax> _work = new HashSet<>(); // For preventing dups
204  public int len() { return _ary.len(); }
205  public void push(Syntax s) { if( !_work.contains(s) ) _work.add(_ary.push(s)); }
206  public Syntax pop() { Syntax s = _ary.pop();_cnt++; _work.remove(s); return s; }
207  //public Syntax pop() { Syntax s = _ary.del( _cnt++%_ary._len); _work.remove(s); return s; }
208  public boolean has(Syntax s) { return _work.contains(s); }
209  public void addAll(Ary<? extends Syntax> ss) { if( ss != null ) for( Syntax s : ss ) push(s); }
210  @Override public String toString() { return _ary.toString(); }
211  }
212 
213  // ---------------------------------------------------------------------
214  // Small classic tree of T2s, immutable, with sharing at the root parts.
215  static class VStack implements Iterable<T2> {
216  final VStack _par;
217  final T2 _nongen;
218  VStack( VStack par, T2 nongen ) { _par=par; _nongen=nongen; }
219  @Override public String toString() {
220  // Collect dups across the forest of types
221  VBitSet dups = new VBitSet();
222  for( VStack vs = this; vs!=null; vs = vs._par )
223  vs._nongen.get_dups(dups);
224  // Now recursively print
225  return str(new SB(),dups).toString();
226  }
227  SB str(SB sb, VBitSet dups) {
228  _nongen.str(sb,new VBitSet(),dups);
229  if( _par!=null ) _par.str(sb.p(" , "),dups);
230  return sb;
231  }
232  @NotNull @Override public Iterator<T2> iterator() { return new Iter(); }
233  private class Iter implements Iterator<T2> {
234  private VStack _vstk;
235  Iter() { _vstk=VStack.this; }
236  @Override public boolean hasNext() { return _vstk!=null; }
237  @Override public T2 next() { T2 v = _vstk._nongen; _vstk = _vstk._par; return v; }
238  }
239  }
240 
241  // ---------------------------------------------------------------------
242  static abstract class Syntax {
245  T2 _t; // Current HM type
246  T2 find() { // U-F find
247  T2 t = _t.find();
248  return t==_t ? t : (_t=t);
249  }
250  T2 debug_find() { return _t.find(); } // Find, without the roll-up
251 
252  // Compute and set a new HM type.
253  // If no change, return false.
254  // If a change, return always true, however:
255  // - If 'work' is null do not change/set anything.
256  // - If 'work' is available, set a new HM in '_t' and update the worklist.
257  abstract boolean hm(Worklist work);
258 
259  abstract int prep_tree(Syntax par, VStack nongen, Worklist work);
260  final void prep_tree_impl( Syntax par, VStack nongen, Worklist work, T2 t ) { _par=par; _t=t; _nongen = nongen; work.push(this); }
261  abstract void prep_lookup_deps(Ident id);
262 
263  abstract T2 lookup(String name); // Lookup name in scope & return type; TODO: pre-cache this.
264 
265  abstract void add_kids(Worklist work); // Add children to worklist
266  void add_occurs(Worklist work){}
267 
268  // Giant Assert: True if OK; all Syntaxs off worklist do not make progress
269  abstract boolean more_work(Worklist work);
270  final boolean more_work_impl(Worklist work) {
271  boolean no_more_work = work.has(this) || !hm(null); // Either on worklist, or no-progress
272  return no_more_work;
273  }
274  // Print for debugger
275  @Override final public String toString() { return str(new SB()).toString(); }
276  abstract SB str(SB sb);
277  // Line-by-line print with more detail
278  public String p() { return p0(new SB(), new VBitSet()).toString(); }
279  final SB p0(SB sb, VBitSet dups) {
280  _t.get_dups(dups);
281  _t.str(p1(sb.i()).p(" "), new VBitSet(),dups).nl();
282  return p2(sb.ii(1),dups).di(1);
283  }
284  abstract SB p1(SB sb); // Self short print
285  abstract SB p2(SB sb, VBitSet dups); // Recursion print
286  }
287 
288  static class Con extends Syntax {
289  final Type _con;
290  Con(Type con) { super(); _con=con; }
291  @Override SB str(SB sb) { return p1(sb); }
292  @Override SB p1(SB sb) { return sb.p(_con instanceof TypeMemPtr ? "str" : _con.toString()); }
293  @Override SB p2(SB sb, VBitSet dups) { return sb; }
294  @Override boolean hm(Worklist work) { return false; }
295  @Override T2 lookup(String name) { throw unimpl("should not reach here"); }
296  @Override void add_kids(Worklist work) { }
297  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) { prep_tree_impl(par, nongen, work, _con==Type.NIL ? T2.make_nil() : T2.make_base(_con)); return 1; }
298  @Override void prep_lookup_deps(Ident id) { throw unimpl("should not reach here"); }
299  @Override boolean more_work(Worklist work) { return more_work_impl(work); }
300  }
301 
302  static class Ident extends Syntax {
303  final String _name;
304  Ident(String name) { _name=name; }
305  @Override SB str(SB sb) { return p1(sb); }
306  @Override SB p1(SB sb) { return sb.p(_name); }
307  @Override SB p2(SB sb, VBitSet dups) { return sb; }
308  @Override boolean hm(Worklist work) {
309  // A boolean if name is from a Let._body (or PRIM) vs Let._def (or
310  // Lambda). Not helpful, as its only useful at the top-layer.
311  // Structural unification requires the 'occurs check' at each internal
312  // layer, which can differ from the top-layer.
313  //boolean occurs_fresh = _par==null /*from prims*/ || _par.is_fresh(_name,this);
314  T2 t = _par==null ? null : _par.lookup(_name); // Lookup in current env
315  if( t==null ) t = PRIMS.get(_name); // Lookup in prims
316  if( t==null )
317  throw new RuntimeException("Parse error, "+_name+" is undefined");
318  return t.find().fresh_unify(find(),_nongen,work);
319  }
320  @Override T2 lookup(String name) { throw unimpl("should not reach here"); }
321  @Override void add_kids(Worklist work) { }
322  @Override void add_occurs(Worklist work) {
323  T2 t = _par==null ? null : _par.lookup(_name); // Lookup in current env
324  if( t==null ) t = PRIMS.get(_name); // Lookup in prims
325  t = t.find();
326  if( t.occurs_in(_par) ) // Got captured in some parent?
327  t.add_deps_work(work); // Need to revisit dependent ids
328  }
329  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
330  prep_tree_impl(par,nongen,work,T2.make_leaf());
331  for( Syntax syn = _par; syn!=null; syn = syn._par )
332  syn.prep_lookup_deps(this);
333  return 1;
334  }
335  @Override void prep_lookup_deps(Ident id) { throw unimpl("should not reach here"); }
336  @Override boolean more_work(Worklist work) { return more_work_impl(work); }
337  }
338 
339  static class Lambda extends Syntax {
340  final String[] _args;
341  final Syntax _body;
343  Lambda(Syntax body, String... args) {
344  _args=args;
345  _body=body;
346  _targs = new T2[args.length];
347  for( int i=0; i<args.length; i++ ) _targs[i] = T2.make_leaf();
348  }
349  @Override SB str(SB sb) {
350  sb.p("{ ");
351  for( String arg : _args ) sb.p(arg).p(' ');
352  return _body.str(sb.p("-> ")).p(" }");
353  }
354  @Override SB p1(SB sb) {
355  sb.p("{ ");
356  for( String arg : _args ) sb.p(arg).p(' ');
357  return sb.p(" -> ... } ");
358  }
359  @Override SB p2(SB sb, VBitSet dups) { return _body.p0(sb,dups); }
360  T2 targ(int i) { T2 targ = _targs[i].find(); return targ==_targs[i] ? targ : (_targs[i]=targ); }
361  @Override boolean hm(Worklist work) {
362  // The normal lambda work
363  boolean progress = false;
364  T2 old = find();
365  if( old.is_fun() ) { // Already a function? Compare-by-parts
366  for( int i=0; i<_targs.length; i++ )
367  if( old.args(i).unify(targ(i),work) )
368  { progress=true; break; }
369  if( !progress && !old.args(_targs.length).unify(_body.find(),work) )
370  return false; // Shortcut: no progress, no allocation
371  }
372  // Make a new T2 for progress
373  T2[] targs = Arrays.copyOf(_targs,_targs.length+1);
374  targs[_targs.length] = _body.find();
375  T2 fun = T2.make_fun(targs);
376  return old.unify(fun,work);
377  }
378  @Override T2 lookup(String name) {
379  for( int i=0; i<_args.length; i++ )
380  if( Util.eq(_args[i],name) ) return targ(i);
381  return _par==null ? null : _par.lookup(name);
382  }
383  @Override void add_kids(Worklist work) { work.push(_body); }
384  @Override void add_occurs(Worklist work) {
385  for( int i=0; i<_targs.length; i++ )
386  if( targ(i).occurs_in_type(find()) ) work.addAll(_targs[i]._deps);
387  }
388  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
389  prep_tree_impl(par,nongen,work,T2.make_leaf());
390  VStack vs = nongen;
391  for( int i=0; i<_targs.length; i++ )
392  vs = new VStack(vs,_targs[i]);
393  return _body.prep_tree(this,vs,work) + 1;
394  }
395  @Override void prep_lookup_deps(Ident id) {
396  for( int i=0; i<_args.length; i++ )
397  if( Util.eq(_args[i],id._name) ) _targs[i].push_update(id);
398  }
399  @Override boolean more_work(Worklist work) {
400  if( !more_work_impl(work) ) return false;
401  return _body.more_work(work);
402  }
403  }
404 
405  static class Let extends Syntax {
406  final String _arg0;
407  final Syntax _def, _body;
409  Let(String arg0, Syntax def, Syntax body) { _arg0=arg0; _body=body; _def=def; _targ=T2.make_leaf(); }
410  @Override SB str(SB sb) { return _body.str(_def.str(sb.p(_arg0).p(" = ")).p("; ")); }
411  @Override SB p1(SB sb) { return sb.p(_arg0).p(" = ... ; ..."); }
412  @Override SB p2(SB sb, VBitSet dups) { _body.p0(sb,dups); return _def.p0(sb,dups); }
413  T2 targ() { T2 targ = _targ.find(); return targ==_targ ? targ : (_targ=targ); }
414  @Override boolean hm(Worklist work) {
415  return targ().unify(_def.find(),work);
416  }
417  @Override T2 lookup(String name) {
418  if( Util.eq(_arg0,name) ) return targ();
419  return _par==null ? null : _par.lookup(name);
420  }
421  @Override void add_kids(Worklist work) { work.push(_body); work.push(_def); }
422  @Override void add_occurs(Worklist work) {
423  if( targ().occurs_in_type(_def.find()) ) work.addAll(_targ._deps);
424  }
425  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
426  prep_tree_impl(par,nongen,work,_body._t);
427  int cnt = _body.prep_tree(this, nongen ,work) +
428  _def .prep_tree(this,new VStack(nongen,_targ),work);
429  _t = _body._t; // Unify 'Let._t' with the '_body'
430  return cnt+1;
431  }
432  @Override void prep_lookup_deps(Ident id) {
433  if( Util.eq(id._name,_arg0) ) _targ.push_update(id);
434  }
435  @Override boolean more_work(Worklist work) {
436  if( !more_work_impl(work) ) return false;
437  return _body.more_work(work) && _def.more_work(work);
438  }
439  }
440 
441  static class Apply extends Syntax {
442  final Syntax _fun;
443  final Syntax[] _args;
444  Apply(Syntax fun, Syntax... args) { _fun = fun; _args = args; }
445  @Override SB str(SB sb) {
446  _fun.str(sb.p("(")).p(" ");
447  for( Syntax arg : _args )
448  arg.str(sb).p(" ");
449  return sb.unchar().p(")");
450  }
451  @Override SB p1(SB sb) { return sb.p("(...)"); }
452  @Override SB p2(SB sb, VBitSet dups) {
453  _fun.p0(sb,dups);
454  for( Syntax arg : _args ) arg.p0(sb,dups);
455  return sb;
456  }
457 
458  @Override boolean hm(Worklist work) {
459  // Unifiying these: make_fun(this.arg0 this.arg1 -> new )
460  // _fun{_fun.arg0 _fun.arg1 -> _fun.rez}
461 
462  // Discover not-nil in the trivial case of directly using the 'if'
463  // primitive against a T2.is_struct(). Will not work if 'if' is some
464  // more hidden or complex function (e.q. '&&' or '||') or the predicate
465  // implies not-null on some other struct.
466  boolean progress = false;
467  T2 str = is_if_nil();
468  if( str!=null && str.is_struct() && str._con==null ) {
469  if( work==null ) return true;
470  progress = true;
471  str._con = Type.NIL; // Add nil to a struct
472  work.addAll(str._deps);
473  }
474 
475  // Progress if:
476  // _fun is not a function
477  // any arg-pair-unifies make progress
478  // this-unify-_fun.return makes progress
479  T2 tfun = _fun.find();
480  if( !tfun.is_fun() ) {
481  if( work==null ) return true; // Will-progress & just-testing
482  T2[] targs = new T2[_args.length+1];
483  for( int i=0; i<_args.length; i++ )
484  targs[i] = _args[i].find();
485  targs[_args.length] = find(); // Return
486  T2 nfun = T2.make_fun(targs);
487  return tfun.unify(nfun,work);
488  }
489 
490  if( tfun._args.length != _args.length+1 )
491  throw new RuntimeException("Mismatched argument lengths");
492  // Check for progress amongst arg pairs
493  for( int i=0; i<_args.length; i++ ) {
494  progress |= tfun.args(i).unify(_args[i].find(),work);
495  if( progress && work==null )
496  return true; // Will-progress & just-testing early exit
497  }
498  progress |= tfun.args(_args.length).unify(find(),work);
499  return progress;
500  }
501  @Override T2 lookup(String name) { return _par==null ? null : _par.lookup(name); }
502  @Override void add_kids(Worklist work) { for( Syntax arg : _args ) work.push(arg); }
503  @Override int prep_tree(Syntax par, VStack nongen, Worklist work) {
504  prep_tree_impl(par,nongen,work,T2.make_leaf());
505  int cnt = 1+_fun.prep_tree(this,nongen,work);
506  for( Syntax arg : _args ) cnt += arg.prep_tree(this,nongen,work);
507  T2 str = is_if_nil();
508  if( str!=null ) str.push_update(this);
509  return cnt;
510  }
511  @Override void prep_lookup_deps(Ident id) { }
512  @Override boolean more_work(Worklist work) {
513  if( !more_work_impl(work) ) return false;
514  if( !_fun.more_work(work) ) return false;
515  for( Syntax arg : _args ) if( !arg.more_work(work) ) return false;
516  return true;
517  }
518  // True if we can refine an if-not-nil
519  private T2 is_if_nil() {
520  return _fun instanceof Ident && Util.eq(((Ident)_fun)._name,"if") && _args[0] instanceof Ident ? _args[0].find() : null;
521  }
522  }
523 
524  // Structure or Records.
525  static class Struct extends Syntax {
526  final String[] _ids;
527  final Syntax[] _flds;
528  Struct( String[] ids, Syntax[] flds ) { _ids=ids; _flds=flds; }
529  @Override SB str(SB sb) {
530  sb.p("@{");
531  for( int i=0; i<_ids.length; i++ ) {
532  sb.p(' ').p(_ids[i]).p(" = ");
533  _flds[i].str(sb);
534  if( i < _ids.length-1 ) sb.p(',');
535  }
536  return sb.p("}");
537  }
538  @Override SB p1(SB sb) { return sb.p("@{ ... } "); }
539  @Override SB p2(SB sb, VBitSet dups) {
540  for( int i=0; i<_ids.length; i++ )
541  _flds[i].p0(sb.p(_ids[i]).p(" = "),dups);
542  return sb;
543  }
544  @Override boolean hm(Worklist work) {
545  // Check for progress before making new
546  T2 old = find();
547  if( old.is_struct() ) { // Already a struct? Compare-by-parts
548  for( int i=0; i<_ids.length; i++ ) {
549  int idx = Util.find(old._ids,_ids[i]);
550  if( idx== -1 || old.args(idx).unify(_flds[i].find(),work) ) { old=null; break; }
551  }
552  if( old!=null ) return false; // Shortcut: no progress, no allocation
553  }
554 
555  // Make a new T2 for progress
556  T2[] t2s = new T2[_ids.length];
557  for( int i=0; i<_ids.length; i++ )
558  t2s[i] = _flds[i].find();
559  T2 tstruct = T2.make_struct(_ids,t2s);
560  return tstruct.unify(find(),work);
561  }
562  @Override T2 lookup(String name) { return _par==null ? null : _par.lookup(name); }
563  @Override void add_kids(Worklist work) { for( Syntax fld : _flds ) work.push(fld); }
564  @Override int prep_tree(Syntax par, VStack nongen, Worklist work) {
565  T2[] t2s = new T2[_ids.length];
566  prep_tree_impl(par, nongen, work, T2.make_struct(_ids,t2s));
567  int cnt = 1; // One for self
568  for( int i=0; i<_flds.length; i++ ) { // Prep all sub-fields
569  cnt += _flds[i].prep_tree(this,nongen,work);
570  t2s[i] = _flds[i].find();
571  }
572  return cnt;
573  }
574  @Override void prep_lookup_deps(Ident id) { }
575  @Override boolean more_work(Worklist work) {
576  if( !more_work_impl(work) ) return false;
577  for( Syntax fld : _flds )
578  if( !fld.more_work(work) )
579  return false;
580  return true;
581  }
582  }
583 
584  // Field lookup in a Struct
585  static class Field extends Syntax {
586  final String _id;
587  final Syntax _str;
588  Field( String id, Syntax str ) { _id=id; _str=str; }
589  @Override SB str(SB sb) { return _str.str(sb.p(".").p(_id).p(' ')); }
590  @Override SB p1 (SB sb) { return sb.p(".").p(_id); }
591  @Override SB p2(SB sb, VBitSet dups) { return _str.p0(sb,dups); }
592  @Override boolean hm(Worklist work) {
593  T2 str = _str.find();
594  int idx = str._ids==null ? -1 : Util.find(str._ids,_id);
595  if( idx==-1 ) // Not a struct or no field, force it to be one
596  return work==null || T2.make_struct(new String[]{_id}, new T2[]{find().push_update(str._deps)}).unify(str, work);
597 
598  // Unify the field
599  return str.args(idx).unify(find(),work);
600  }
601  @Override T2 lookup(String name) { return _par==null ? null : _par.lookup(name); }
602  @Override void add_kids(Worklist work) { work.push(_str); }
603  @Override void add_occurs(Worklist work) { _str.add_occurs(work); }
604  @Override int prep_tree(Syntax par, VStack nongen, Worklist work) {
605  prep_tree_impl(par, nongen, work, T2.make_leaf());
606  return _str.prep_tree(this,nongen,work)+1;
607  }
608  @Override void prep_lookup_deps(Ident id) { }
609  @Override boolean more_work(Worklist work) {
610  if( !more_work_impl(work) ) return false;
611  return _str.more_work(work);
612  }
613  }
614 
615  // ---------------------------------------------------------------------
616  // T2 types form a Lattice, with 'unify' same as 'meet'. T2's form a DAG
617  // (cycles if i allow recursive unification) with sharing. Each Syntax has a
618  // T2, and the forest of T2s can share. Leaves of a T2 can be either a
619  // simple concrete base type, or a sharable leaf. Unify is structural, and
620  // where not unifyable the union is replaced with an Error.
621  static class T2 {
622  private static int CNT=0;
623  final int _uid;
624 
625  // A plain type variable starts with a 'V', and can unify directly.
626  // Everything else is structural - during unification they must match names
627  // and arguments and Type constants.
628  @NotNull String _name; // name, e.g. "->" or "pair" or "V123" or "base"
629 
630  // Structural parts to unify with, or slot 0 is used during normal U-F
631  T2 @NotNull [] _args;
632 
633  // Base types carry a concrete Type
635 
636  // Structs have field names
637  @NotNull String[] _ids;
638 
639  // Dependent (non-local) tvars to revisit
641 
642 
643  static T2 make_fun(T2... args) { return new T2("->",null,null,args); }
644  static T2 make_leaf() { return new T2("V"+CNT,null,null,new T2[1]); }
645  static T2 make_base(Type con) { return new T2("Base",con,null); }
646  static T2 make_nil() { return new T2("Nil",null,null); }
647  static T2 make_struct( String[] ids, T2[] flds ) { return new T2("@{}", null,ids,flds); }
648  static T2 prim(String name, T2... args) { return new T2(name,null,null,args); }
649  T2 copy() { return new T2(_name,_con,_ids,new T2[_args.length]); }
650 
651  private T2(@NotNull String name, Type con, String[] ids, T2 @NotNull ... args) {
652  _uid = CNT++;
653  _name= name;
654  _con = con;
655  _ids = ids;
656  _args= args;
657  }
658 
659  // A type var, not a concrete leaf. Might be U-Fd or not.
660  boolean is_leaf() { return _name.charAt(0)=='V' || (isa("Base") && _con==null); }
661  boolean no_uf() { return !is_leaf() || _args[0]==null; }
662  boolean isa(String name) { return Util.eq(_name,name); }
663  boolean is_base() { return isa("Base") && _con!=null; }
664  boolean is_nil() { return isa("Nil"); }
665  boolean is_fun () { return isa("->"); }
666  boolean is_struct() { return isa("@{}"); }
667 
668  // U-F find
669  T2 find() {
670  if( !is_leaf() ) return this; // Shortcut
671  T2 u = _args[0];
672  if( u==null ) return this; // Shortcut
673  if( u.no_uf() ) return u; // Shortcut
674  // U-F fixup
675  while( u.is_leaf() && u._args[0]!=null ) u = u._args[0];
676  T2 v = this, v2;
677  while( !v.is_leaf() && (v2=v._args[0])!=u ) { v._args[0]=u; v = v2; }
678  return u;
679  }
680  // U-F find on the args array
681  T2 args(int i) {
682  T2 u = _args[i];
683  T2 uu = u.find();
684  return u==uu ? uu : (_args[i]=uu);
685  }
686 
687  // U-F union; this becomes that; returns 'that'.
688  // No change if only testing, and reports progress.
689  boolean union(T2 that, Worklist work) {
690  assert no_uf(); // Cannot union twice
691  if( this==that ) return false;
692  if( work==null ) return true; // Report progress without changing
693  // Worklist: put updates on the worklist for revisiting
694  if( _deps != null ) {
695  work.addAll(_deps); // Re-Apply
696  // Merge update lists, for future unions
697  if( that._deps==null && that.is_leaf() ) that._deps = _deps;
698  else
699  for( Syntax dep : _deps ) that.push_update(dep);
700  _deps = null;
701  }
702  _args[0] = that; // U-F update
703  if( _name.charAt(0)!='V' ) _name = "V"+_uid; // Flag as a leaf & unified
704  assert !no_uf();
705  return true;
706  }
707 
708  // Unify a struct with nil
709  boolean or0(T2 that, Worklist work) {
710  assert is_nil() && that.is_struct();
711  if( work==null ) return that._con==null; // Progress if moving from not-nil to nilable
712  if( that._con == Type.NIL ) return false;// Already nilable
713  _args = new T2[1]; // Room for U-F
714  that._con=Type.NIL;
715  return union(that,work);
716  }
717 
718  // Structural unification.
719  // Returns false if no-change, true for change.
720  // If work is null, does not actually change anything, just reports progress.
721  // If work and change, unifies 'this' into 'that' (changing both), and
722  // updates the worklist.
723  static private final HashMap<Long,T2> DUPS = new HashMap<>();
724  boolean unify( T2 that, Worklist work ) {
725  if( this==that ) return false;
726  assert DUPS.isEmpty();
727  boolean progress = _unify(that,work);
728  DUPS.clear();
729  return progress;
730  }
731 
732  // Structural unification, 'this' into 'that'. No change if just testing
733  // (work is null) and returns 'that' if progress. If updating, both 'this'
734  // and 'that' are the same afterwards.
735  private boolean _unify(T2 that, Worklist work) {
736  assert no_uf() && that.no_uf();
737  if( this==that ) return false;
738 
739  // two leafs union in either order, so keep lower uid
740  if( is_leaf() && that.is_leaf() && _uid<that._uid ) return that.union(this,work);
741  if( is_leaf() ) return union(that,work);
742  if( that.is_leaf() ) return that.union(this,work);
743  if( is_base() && that.is_base() ) return unify_base(that,work);
744  // Unify struct with nil
745  if( is_nil() && that.is_struct() ) return or0(that,work);
746  if( that.is_nil() && is_struct() ) return that.or0(this,work);
747 
748  if( !Util.eq(_name,that._name) )
749  throw new RuntimeException("Cannot unify "+this+" and "+that);
750  assert _args!=that._args; // Not expecting to share _args and not 'this'
751  if( !is_struct() && _args.length != that._args.length )
752  throw new RuntimeException("Cannot unify "+this+" and "+that);
753 
754  // Cycle check
755  long luid = dbl_uid(that);
756  T2 rez = DUPS.get(luid);
757  assert rez==null || rez==that;
758  if( rez!=null ) return false; // Been there, done that
759  DUPS.put(luid,that); // Close cycles
760 
761  if( work==null ) return true; // Here we definitely make progress; bail out early if just testing
762 
763  // Structural recursion unification.
764  // Structs unify only on matching fields, and add missing fields.
765  if( is_struct() ) {
766  // Unification for structs is more complicated; args are aligned via
767  // field names and not by position.
768  for( int i=0; i<_ids.length; i++ ) { // For all fields in LHS
769  int idx = Util.find(that._ids,_ids[i]);
770  if( idx==-1 ) that.add_fld(_ids[i],args(i), work); // Extend 'that' with matching field from 'this'
771  else args(i)._unify(that.args(idx),work); // Unify matching field
772  that = that.find(); // Recursively, might have already rolled this up
773  }
774  if( _con!=null && that._con==null ) that._con=Type.NIL;
775  if( this==that ) return true; // Might have unioned this-into-that recursively, exit now with progress
776  } else {
777  for( int i=0; i<_args.length; i++ ) // For all fields in LHS
778  args(i)._unify(that.args(i),work);
779  }
780  return union(that,work);
781  }
782 
783  private void add_fld(String id, T2 fld, Worklist work) {
784  assert is_struct();
785  int len = _ids.length;
786  _ids = Arrays.copyOf( _ids,len+1);
787  _args = Arrays.copyOf(_args,len+1);
788  _ids [len] = id ;
789  _args[len] = fld;
790  work.addAll(_deps); //
791  }
792 
793  private long dbl_uid(T2 t) { return ((long)_uid<<32)|t._uid; }
794 
795  private boolean unify_base(T2 that, Worklist work) {
796  Type con = _con.meet(that._con);
797  if( con==that._con ) return false; // No progress
798  if( work==null ) return true;
799  that._con = con; // Yes progress, but no update if null work
800  _args = new T2[1]; // Room for a forwarding pointer
801  _con=null; // Flip from 'Base' to 'Leaf'
802  return union(that,work);
803  }
804  private boolean fresh_base(T2 that, Worklist work) {
805  Type con = _con.meet(that._con);
806  if( con==that._con ) return false; // No progress
807  if( work==null ) return true;
808  that._con = con; // Yes progress, but no update if null work
809  return true;
810  }
811 
812  // Make a (lazy) fresh copy of 'this' and unify it with 'that'. This is
813  // the same as calling 'fresh' then 'unify', without the clone of 'this'.
814  // The Syntax is used when making the 'fresh' copy for the occurs_check;
815  // it is another version of the 'nongen' set.
816  // Returns progress.
817  // If work is null, we are testing only and make no changes.
818  static private final HashMap<T2,T2> VARS = new HashMap<>();
819  boolean fresh_unify(T2 that, VStack nongen, Worklist work) {
820  assert VARS.isEmpty() && DUPS.isEmpty();
821  int old = CNT;
822  boolean progress = _fresh_unify(that,nongen,work);
823  VARS.clear(); DUPS.clear();
824  if( work==null && old!=CNT && DEBUG_LEAKS )
825  throw unimpl("busted, made T2s but just testing");
826  return progress;
827  }
828 
829  // Outer recursive version, wraps a VARS check around other work
830  private boolean _fresh_unify(T2 that, VStack nongen, Worklist work) {
831  assert no_uf() && that.no_uf();
832  T2 prior = VARS.get(this);
833  if( prior!=null ) // Been there, done that
834  return prior.find()._unify(that,work); // Also 'prior' needs unification with 'that'
835  if( cycle_equals(that) ) return vput(that,false);
836 
837  // Attempting to pre-compute occurs_in, by computing 'is_fresh' in the
838  // Ident.hm() call does NOT work. The 'is_fresh' is for the top-layer
839  // only, not the internal layers. As soon as we structural recurse down
840  // a layer, 'is_fresh' does not correlate with an occurs_in check.
841  if( nongen_in(nongen) ) return vput(that,_unify(that,work)); // Famous 'occurs-check', switch to normal unify
842  if( this.is_leaf() ) return vput(that,false); // Lazy map LHS tvar to RHS
843  if( that.is_leaf() ) // RHS is a tvar; union with a deep copy of LHS
844  return work==null || vput(that,that.union(_fresh(nongen),work));
845  // Bases MEET cons in RHS
846  if( is_base() && that.is_base() ) return vput(that,fresh_base(that,work));
847  // Unify struct with nil
848  if( is_nil() && that.is_struct() ) return vput(that,or0(that,work));
849  if( that.is_nil() && is_struct() )
850  return work==null || vput(that,that.or0(_fresh(nongen),work));
851 
852  if( !Util.eq(_name,that._name) ||
853  (!is_struct() && _args.length != that._args.length) )
854  throw new RuntimeException("Cannot unify "+this+" and "+that);
855 
856  // Structural recursion unification, lazy on LHS
857  vput(that,false); // Early set, to stop cycles
858  boolean progress = false;
859  if( is_struct() )
860  progress = _fresh_unify_struct(that,nongen,work);
861  else {
862  for( int i=0; i<_args.length; i++ ) {
863  progress |= args(i)._fresh_unify(that.args(i),nongen,work);
864  if( progress && work==null ) return true;
865  }
866  }
867  return progress;
868  }
869 
870  // Unification with structs must honor field names.
871  private boolean _fresh_unify_struct(T2 that, VStack nongen, Worklist work) {
872  assert is_struct() && that.is_struct();
873  if( _con!=null && that._con==null ) {
874  if( work==null ) return true; // Will progress
875  that._con = Type.NIL; // Allow nil
876  }
877  boolean progress = false;
878  for( int i=0; i<_args.length; i++ ) {
879  int idx = Util.find(that._ids,_ids[i]);
880  if( idx == -1 ) { // Missing field on RHS
881  if( work==null ) return true; // Will definitely make progress
882  progress = true;
883  that.add_fld(_ids[i],args(i)._fresh(nongen), work);
884  } else
885  progress |= args(i)._fresh_unify(that.args(idx),nongen,work);
886  if( progress && work==null ) return true;
887  }
888  return progress;
889  }
890 
891  private boolean vput(T2 that, boolean progress) { VARS.put(this,that); return progress; }
892 
893  // Return a fresh copy of 'this'
894  private T2 _fresh(VStack nongen) {
895  assert no_uf();
896  T2 rez = VARS.get(this);
897  if( rez!=null ) return rez; // Been there, done that
898 
899  if( is_leaf() ) {
900  // If occurs_in lexical scope, keep same variable, else make a new leaf
901  T2 t = nongen_in(nongen) ? this : T2.make_leaf();
902  VARS.put(this,t);
903  return t;
904  } else { // Structure is deep-replicated
905  T2 t = copy();
906  VARS.put(this,t); // Stop cyclic structure looping
907  for( int i=0; i<_args.length; i++ )
908  t._args[i] = args(i)._fresh(nongen);
909  return t;
910  }
911  }
912 
913  private static final VBitSet ODUPS = new VBitSet();
914  boolean occurs_in(Syntax syn) {
915  if( syn==null ) return false;
916  if( is_base() ) return false;
917  assert ODUPS.isEmpty();
918  boolean found = _occurs_in(syn);
919  ODUPS.clear();
920  return found;
921  }
922  boolean occurs_in_type(T2 x) {
923  assert ODUPS.isEmpty();
924  boolean found = _occurs_in_type(x);
925  ODUPS.clear();
926  return found;
927  }
928  boolean _occurs_in(Syntax syn) {
929  for( ; syn!=null; syn=syn._par )
930  if( _occurs_in_type(syn.find()) )
931  return true;
932  return false;
933  }
934 
935  boolean _occurs_in_type(T2 x) {
936  assert no_uf() && x.no_uf();
937  if( x==this ) return true;
938  if( ODUPS.tset(x._uid) ) return false; // Been there, done that
939  if( !x.is_leaf() )
940  for( int i=0; i<x._args.length; i++ )
941  if( _occurs_in_type(x.args(i)) )
942  return true;
943  return false;
944  }
945 
946  boolean nongen_in(VStack syn) {
947  if( syn==null ) return false;
948  assert ODUPS.isEmpty();
949  boolean found = _nongen_in(syn);
950  ODUPS.clear();
951  return found;
952  }
953  boolean _nongen_in(VStack nongen) {
954  for( T2 t2 : nongen )
955  if( _occurs_in_type(t2.find()) )
956  return true;
957  return false;
958  }
959 
960  // Test for structural equivalence, including cycles
961  static private final HashMap<T2,T2> CDUPS = new HashMap<>();
962  boolean cycle_equals(T2 t) {
963  assert CDUPS.isEmpty();
964  boolean rez = _cycle_equals(t);
965  CDUPS.clear();
966  return rez;
967  }
968  boolean _cycle_equals(T2 t) {
969  assert no_uf() && t.no_uf();
970  if( this==t ) return true;
971  if( is_base() && t.is_base() )
972  return _con==t._con; // Base-cases have to be completely identical
973  if( !Util.eq(_name,t._name) || // Wrong type-var names
974  _args.length != t._args.length ) // Mismatched sizes
975  return false;
976  if( _args==t._args ) return true;
977  // Cycles stall the equal/unequal decision until we see a difference.
978  T2 tc = CDUPS.get(this);
979  if( tc!=null )
980  return tc==t; // Cycle check; true if both cycling the same
981  CDUPS.put(this,t);
982  if( is_struct() ) // Struct equality honors field names without regard to order
983  return _cycle_equals_struct(t);
984  for( int i=0; i<_args.length; i++ )
985  if( !args(i)._cycle_equals(t.args(i)) )
986  return false;
987  return true;
988  }
989 
990  private boolean _cycle_equals_struct(T2 t) {
991  assert is_struct() && t.is_struct();
992  if( _con != t._con ) return false;
993  for( int i=0; i<_args.length; i++ ) {
994  int idx = Util.find(t._ids,_ids[i]);
995  if( idx==-1 || !args(i)._cycle_equals(t.args(idx)) )
996  return false;
997  }
998  return true;
999  }
1000 
1001  // This is a T2 function that is the target of 'fresh', i.e., this function
1002  // might be fresh-unified with some other function. Push the application
1003  // down the function parts; if any changes the fresh-application may make
1004  // progress.
1005  static final VBitSet UPDATE_VISIT = new VBitSet();
1006  T2 push_update( Ary<Syntax> as ) { if( as != null ) for( Syntax a : as ) push_update(a); return this; }
1007  void push_update( Syntax a) { assert UPDATE_VISIT.isEmpty(); push_update_impl(a); UPDATE_VISIT.clear(); }
1008  private void push_update_impl(Syntax a) {
1009  assert no_uf();
1010  if( UPDATE_VISIT.tset(_uid) ) return;
1011  if( _deps==null ) _deps = new Ary<>(Syntax.class);
1012  if( _deps.find(a)==-1 ) _deps.push(a);
1013  for( int i=0; i<_args.length; i++ )
1014  if( _args[i]!=null )
1015  args(i).push_update_impl(a);
1016  }
1017 
1018  void add_deps_work( Worklist work ) { assert UPDATE_VISIT.isEmpty(); add_deps_work_impl(work); UPDATE_VISIT.clear(); }
1019  private void add_deps_work_impl( Worklist work ) {
1020  if( is_leaf() || _args.length==0 ) {
1021  work.addAll(_deps);
1022  } else {
1023  if( UPDATE_VISIT.tset(_uid) ) return;
1024  for( int i=0; i<_args.length; i++ )
1025  args(i).add_deps_work_impl(work);
1026  }
1027  }
1028 
1029  // -----------------
1030  // Glorious Printing
1031 
1032  // Look for dups, in a tree or even a forest (which Syntax.p() does)
1033  VBitSet get_dups(VBitSet dups) { return _get_dups(new VBitSet(),dups); }
1035  if( visit.tset(_uid) && no_uf() ) dups.set(_uid);
1036  else
1037  for( T2 t : _args )
1038  if( t!=null )
1039  t._get_dups(visit,dups);
1040  return dups;
1041  }
1042 
1043  // Fancy print for Debuggers - includes explicit U-F re-direction.
1044  // Does NOT roll-up U-F, has no side-effects.
1045  @Override public String toString() { return str(new SB(), new VBitSet(), get_dups(new VBitSet()) ).toString(); }
1046  SB str(SB sb, VBitSet visit, VBitSet dups) {
1047  if( is_leaf() || is_base() ) {
1048  if( is_base() ) sb.p(_con instanceof TypeMemPtr ? "str" : _con.toString()); else sb.p(_name);
1049  return _args.length==0 || _args[0]==null ? sb : _args[0].str(sb.p(">>"), visit, dups);
1050  }
1051  boolean dup = dups.get(_uid);
1052  if( dup ) sb.p("$V").p(_uid);
1053  if( visit.tset(_uid) && dup ) return sb;
1054  if( dup ) sb.p(':');
1055 
1056  // Special printing for functions
1057  if( is_fun() ) {
1058  sb.p("{ ");
1059  for( int i=0; i<_args.length-1; i++ )
1060  str(sb,visit,_args[i],dups).p(" ");
1061  return str(sb.p("-> "),visit,_args[_args.length-1],dups).p(" }");
1062  }
1063 
1064  // Special printing for structures
1065  if( is_struct() ) {
1066  sb.p("@{");
1067  for( int i=0; i<_ids.length; i++ )
1068  str(sb.p(' ').p(_ids[i]).p(" = "),visit,_args[i],dups).p(',');
1069  sb.unchar().p("}");
1070  if( _con==Type.NIL ) sb.p('?');
1071  return sb;
1072  }
1073 
1074  // Generic structural T2
1075  sb.p("(").p(_name).p(" ");
1076  for( T2 t : _args ) str(sb,visit,t,dups).p(" ");
1077  return sb.unchar().p(")");
1078  }
1079  static private SB str(SB sb, VBitSet visit, T2 t, VBitSet dups) { return t==null ? sb.p("_") : t.str(sb,visit,dups); }
1080 
1081  // Same as toString but calls find(). Can thus side-effect & roll-up U-Fs, so not a toString
1082  public String p() { return p(get_dups(new VBitSet())); }
1083  private static int VCNT;
1084  private static final HashMap<T2,Integer> VNAMES = new HashMap<>();
1085  String p(VBitSet dups) { VCNT=0; VNAMES.clear(); return find()._p(new SB(), new VBitSet(), dups).toString(); }
1086  private SB _p(SB sb, VBitSet visit, VBitSet dups) {
1087  assert no_uf();
1088  if( is_base() ) return sb.p(_con instanceof TypeMemPtr ? "str" : _con.toString() );
1089  if( is_leaf() || dups.get(_uid) ) { // Leafs or Duplicates? Take some effort to pretty-print cycles
1090  Integer ii = VNAMES.get(this);
1091  if( ii==null ) VNAMES.put(this,ii=VCNT++);
1092  // 2nd and later visits use the short form
1093  boolean later = !is_leaf() && visit.tset(_uid);
1094  if( later ) sb.p('$');
1095  char c = (char)('A'+ii);
1096  if( c<'V' ) sb.p(c); else sb.p("V"+ii);
1097  if( is_leaf() || later ) return sb;
1098  // First visit prints the V._uid and the type
1099  sb.p(':');
1100  }
1101 
1102  // Special printing for functions: { arg -> body }
1103  if( is_fun() ) {
1104  sb.p("{ ");
1105  for( int i=0; i<_args.length-1; i++ )
1106  args(i)._p(sb,visit,dups).p(" ");
1107  return args(_args.length-1)._p(sb.p("-> "),visit,dups).p(" }");
1108  }
1109 
1110  // Special printing for structures: @{ fld0 = body, fld1 = body, ... }
1111  if( is_struct() ) {
1112  sb.p("@{");
1113  for( int i=0; i<_ids.length; i++ )
1114  args(i)._p(sb.p(' ').p(_ids[i]).p(" = "),visit,dups).p(',');
1115  sb.unchar().p("}");
1116  if( _con==Type.NIL ) sb.p('?');
1117  return sb;
1118  }
1119 
1120  // Generic structural T2: (fun arg0 arg1...)
1121  sb.p("(").p(_name).p(" ");
1122  for( int i=0; i<_args.length; i++ ) args(i)._p(sb,visit,dups).p(" ");
1123  return sb.unchar().p(")");
1124  }
1125 
1126  static void reset() { CNT=0; DUPS.clear(); VARS.clear(); ODUPS.clear(); CDUPS.clear(); UPDATE_VISIT.clear(); }
1127  }
1128 
1129 }
com.cliffc.aa.HM.HM7.Apply.p2
SB p2(SB sb, VBitSet dups)
Definition: HM7.java:452
com.cliffc.aa.HM.HM7.T2.unify_base
boolean unify_base(T2 that, Worklist work)
Definition: HM7.java:795
com.cliffc.aa.HM.HM7.T2.copy
T2 copy()
Definition: HM7.java:649
com.cliffc.aa.HM.HM7.T2.str
SB str(SB sb, VBitSet visit, VBitSet dups)
Definition: HM7.java:1046
com.cliffc.aa.HM.HM7.T2._p
SB _p(SB sb, VBitSet visit, VBitSet dups)
Definition: HM7.java:1086
com.cliffc.aa.HM.HM7.Let._body
final Syntax _body
Definition: HM7.java:407
com.cliffc.aa.HM.HM7.Syntax.more_work
abstract boolean more_work(Worklist work)
com.cliffc.aa.HM.HM7.term
static Syntax term()
Definition: HM7.java:103
com.cliffc.aa.HM.HM7.T2._fresh_unify_struct
boolean _fresh_unify_struct(T2 that, VStack nongen, Worklist work)
Definition: HM7.java:871
com.cliffc.aa.HM.HM7.T2.find
T2 find()
Definition: HM7.java:669
com.cliffc.aa.HM.HM7
Definition: HM7.java:23
com.cliffc.aa.HM.HM7.Worklist._cnt
int _cnt
Definition: HM7.java:201
com.cliffc.aa.HM.HM7.toString
String toString()
Definition: HM7.java:95
com.cliffc.aa.util.Ary.push
E push(E e)
Add element in amortized constant time.
Definition: Ary.java:58
com.cliffc.aa.HM.HM7.T2.occurs_in
boolean occurs_in(Syntax syn)
Definition: HM7.java:914
com.cliffc.aa.HM.HM7.Field
Definition: HM7.java:585
com.cliffc.aa.HM.HM7.Struct.str
SB str(SB sb)
Definition: HM7.java:529
com.cliffc.aa.util.Util.find
static int find(int[] es, int e)
Definition: Util.java:6
com.cliffc.aa.HM.HM7.T2.p
String p()
Definition: HM7.java:1082
com.cliffc.aa.HM.HM7.Ident.lookup
T2 lookup(String name)
Definition: HM7.java:320
com.cliffc.aa.util.Util.eq
static boolean eq(String s0, String s1)
Definition: Util.java:16
com.cliffc.aa.HM.HM7.Lambda.add_kids
void add_kids(Worklist work)
Definition: HM7.java:383
com.cliffc.aa.HM.HM7.Field.hm
boolean hm(Worklist work)
Definition: HM7.java:592
com.cliffc.aa.HM.HM7.Ident.p1
SB p1(SB sb)
Definition: HM7.java:306
com.cliffc.aa.HM.HM7.Struct.Struct
Struct(String[] ids, Syntax[] flds)
Definition: HM7.java:528
com.cliffc.aa.util.SB.ii
SB ii(int i)
Definition: SB.java:44
com.cliffc
com.cliffc.aa.HM.HM7.Apply._args
final Syntax[] _args
Definition: HM7.java:443
com.cliffc.aa.HM.HM7.Field.p1
SB p1(SB sb)
Definition: HM7.java:590
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.HM7.Apply.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM7.java:503
com.cliffc.aa.HM.HM7.Con.hm
boolean hm(Worklist work)
Definition: HM7.java:294
com.cliffc.aa.HM.HM7.Let._arg0
final String _arg0
Definition: HM7.java:406
com.cliffc.aa.HM.HM7.VStack.VStack
VStack(VStack par, T2 nongen)
Definition: HM7.java:218
com.cliffc.aa.HM.HM7.Struct.lookup
T2 lookup(String name)
Definition: HM7.java:562
com.cliffc.aa.HM.HM7.T2.union
boolean union(T2 that, Worklist work)
Definition: HM7.java:689
com.cliffc.aa.HM.HM7.Field.add_kids
void add_kids(Worklist work)
Definition: HM7.java:602
com.cliffc.aa.HM.HM7.Apply.more_work
boolean more_work(Worklist work)
Definition: HM7.java:512
com.cliffc.aa.HM.HM7.Syntax.add_occurs
void add_occurs(Worklist work)
Definition: HM7.java:266
com.cliffc.aa.HM.HM7.Apply.add_kids
void add_kids(Worklist work)
Definition: HM7.java:502
com.cliffc.aa.HM.HM7.Apply
Definition: HM7.java:441
com.cliffc.aa.util
Definition: AbstractEntry.java:1
com.cliffc.aa.HM.HM7.T2.fresh_base
boolean fresh_base(T2 that, Worklist work)
Definition: HM7.java:804
com.cliffc.aa.type.TypeInt
Definition: TypeInt.java:9
com.cliffc.aa.HM.HM7.require
static void require(String s)
Definition: HM7.java:190
com.cliffc.aa.HM.HM7.Ident
Definition: HM7.java:302
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.HM.HM7.T2.make_struct
static T2 make_struct(String[] ids, T2[] flds)
Definition: HM7.java:647
com.cliffc.aa.HM.HM7.Syntax._par
Syntax _par
Definition: HM7.java:243
com.cliffc.aa.HM.HM7.Syntax.p1
abstract SB p1(SB sb)
com.cliffc.aa.util.SB.clear
SB clear()
Definition: SB.java:61
com.cliffc.aa.type.TypeFlt
Definition: TypeFlt.java:9
com.cliffc.aa.HM.HM7.T2.make_nil
static T2 make_nil()
Definition: HM7.java:646
com.cliffc.aa.HM.HM7.Con.more_work
boolean more_work(Worklist work)
Definition: HM7.java:299
com.cliffc.aa.HM.HM7.Let.lookup
T2 lookup(String name)
Definition: HM7.java:417
com.cliffc.aa.util.Ary
Definition: Ary.java:11
com.cliffc.aa.HM.HM7.Syntax.prep_tree
abstract int prep_tree(Syntax par, VStack nongen, Worklist work)
com.cliffc.aa.HM.HM7.T2._name
String _name
Definition: HM7.java:628
com.cliffc.aa.HM.HM7.T2._deps
Ary< Syntax > _deps
Definition: HM7.java:640
com.cliffc.aa.HM.HM7.T2._nongen_in
boolean _nongen_in(VStack nongen)
Definition: HM7.java:953
com.cliffc.aa.HM.HM7.Syntax._nongen
VStack _nongen
Definition: HM7.java:244
com.cliffc.aa.HM.HM7.Lambda.targ
T2 targ(int i)
Definition: HM7.java:360
com.cliffc.aa.HM.HM7.T2.args
T2 args(int i)
Definition: HM7.java:681
com.cliffc.aa.HM.HM7.T2.no_uf
boolean no_uf()
Definition: HM7.java:661
com.cliffc.aa.HM.HM7.Syntax.str
abstract SB str(SB sb)
com.cliffc.aa.HM.HM7.Apply._fun
final Syntax _fun
Definition: HM7.java:442
com.cliffc.aa.HM.HM7.Worklist.addAll
void addAll(Ary<? extends Syntax > ss)
Definition: HM7.java:209
com.cliffc.aa.HM.HM7.Syntax.p
String p()
Definition: HM7.java:278
com.cliffc.aa.HM.HM7.VStack.Iter.next
T2 next()
Definition: HM7.java:237
com.cliffc.aa.HM.HM7.T2._occurs_in_type
boolean _occurs_in_type(T2 x)
Definition: HM7.java:935
com.cliffc.aa.HM.HM7.T2.is_fun
boolean is_fun()
Definition: HM7.java:665
com.cliffc.aa.HM.HM7.id
static String id()
Definition: HM7.java:158
com.cliffc.aa.type.TypeInt.con
static TypeInt con(long con)
Definition: TypeInt.java:37
com.cliffc.aa.HM.HM7.T2.vput
boolean vput(T2 that, boolean progress)
Definition: HM7.java:891
com.cliffc.aa.HM.HM7.T2.reset
static void reset()
Definition: HM7.java:1126
com.cliffc.aa.HM.HM7.Syntax
Definition: HM7.java:242
com.cliffc.aa.HM.HM7.Field.more_work
boolean more_work(Worklist work)
Definition: HM7.java:609
com.cliffc.aa.HM.HM7.ID
static final SB ID
Definition: HM7.java:157
com.cliffc.aa.HM.HM7.string
static Syntax string()
Definition: HM7.java:176
com.cliffc.aa.HM.HM7.Apply.hm
boolean hm(Worklist work)
Definition: HM7.java:458
com.cliffc.aa.HM.HM7.Struct._ids
final String[] _ids
Definition: HM7.java:526
com.cliffc.aa.HM.HM7.Let._targ
T2 _targ
Definition: HM7.java:408
com.cliffc.aa.HM.HM7.T2.UPDATE_VISIT
static final VBitSet UPDATE_VISIT
Definition: HM7.java:1005
com.cliffc.aa.HM.HM7.Lambda.Lambda
Lambda(Syntax body, String... args)
Definition: HM7.java:343
com.cliffc.aa.HM.HM7.Ident.p2
SB p2(SB sb, VBitSet dups)
Definition: HM7.java:307
com.cliffc.aa.HM.HM7.Lambda.str
SB str(SB sb)
Definition: HM7.java:349
com.cliffc.aa.HM.HM7.T2.VARS
static final HashMap< T2, T2 > VARS
Definition: HM7.java:818
com.cliffc.aa.HM.HM7.PRIMS
static final HashMap< String, T2 > PRIMS
Definition: HM7.java:24
com.cliffc.aa.type.Type.meet
final Type meet(Type t)
Definition: Type.java:412
com.cliffc.aa.HM.HM7.T2.make_fun
static T2 make_fun(T2... args)
Definition: HM7.java:643
com.cliffc.aa.AA.unimpl
static RuntimeException unimpl()
Definition: AA.java:10
com.cliffc.aa.HM.HM7.Syntax.prep_tree_impl
final void prep_tree_impl(Syntax par, VStack nongen, Worklist work, T2 t)
Definition: HM7.java:260
com.cliffc.aa.HM.HM7.Syntax.toString
final String toString()
Definition: HM7.java:275
com.cliffc.aa.HM.HM7.Lambda.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM7.java:395
com.cliffc.aa.HM.HM7.VStack.str
SB str(SB sb, VBitSet dups)
Definition: HM7.java:227
com.cliffc.aa.HM.HM7.Apply.p1
SB p1(SB sb)
Definition: HM7.java:451
com.cliffc.aa.HM.HM7.Worklist.push
void push(Syntax s)
Definition: HM7.java:205
com.cliffc.aa.HM.HM7.Worklist.toString
String toString()
Definition: HM7.java:210
com.cliffc.aa.util.SB.unchar
SB unchar()
Definition: SB.java:58
com.cliffc.aa.HM.HM7.Con.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM7.java:297
Iterable
com.cliffc.aa.HM.HM7.VStack._par
final VStack _par
Definition: HM7.java:216
com.cliffc.aa.HM.HM7.Let.hm
boolean hm(Worklist work)
Definition: HM7.java:414
com.cliffc.aa.HM.HM7.Lambda.add_occurs
void add_occurs(Worklist work)
Definition: HM7.java:384
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.HM7.T2.push_update
T2 push_update(Ary< Syntax > as)
Definition: HM7.java:1006
com.cliffc.aa.HM.HM7.T2.dbl_uid
long dbl_uid(T2 t)
Definition: HM7.java:793
com.cliffc.aa.type.TypeInt.INT64
static final TypeInt INT64
Definition: TypeInt.java:39
com.cliffc.aa.HM.HM7.isWS
static boolean isWS(byte c)
Definition: HM7.java:185
com.cliffc.aa.type.TypeFlt.con
static Type con(double con)
Definition: TypeFlt.java:36
com.cliffc.aa.HM.HM7.T2._con
Type _con
Definition: HM7.java:634
com.cliffc.aa.HM.HM7.Let.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM7.java:432
com.cliffc.aa.HM.HM7.T2.T2
T2(@NotNull String name, Type con, String[] ids, T2 @NotNull ... args)
Definition: HM7.java:651
com.cliffc.aa.HM.HM7.Field.lookup
T2 lookup(String name)
Definition: HM7.java:601
com.cliffc.aa.HM.HM7.T2._cycle_equals_struct
boolean _cycle_equals_struct(T2 t)
Definition: HM7.java:990
com.cliffc.aa.HM.HM7.T2.CDUPS
static final HashMap< T2, T2 > CDUPS
Definition: HM7.java:961
com.cliffc.aa.HM.HM7.Apply.Apply
Apply(Syntax fun, Syntax... args)
Definition: HM7.java:444
com.cliffc.aa.HM.HM7.Syntax.find
T2 find()
Definition: HM7.java:246
com.cliffc.aa.HM.HM7.isDigit
static boolean isDigit(byte c)
Definition: HM7.java:186
com.cliffc.aa.HM.HM7.Worklist.pop
Syntax pop()
Definition: HM7.java:206
com.cliffc.aa.HM.HM7.skipWS
static byte skipWS()
Definition: HM7.java:181
com.cliffc.aa.HM.HM7.T2.make_base
static T2 make_base(Type con)
Definition: HM7.java:645
com.cliffc.aa.HM.HM7.Let
Definition: HM7.java:405
com.cliffc.aa.HM.HM7.Con.p2
SB p2(SB sb, VBitSet dups)
Definition: HM7.java:293
com.cliffc.aa.HM.HM7.Lambda.more_work
boolean more_work(Worklist work)
Definition: HM7.java:399
com.cliffc.aa.HM.HM7.VStack.iterator
Iterator< T2 > iterator()
Definition: HM7.java:232
com.cliffc.aa.HM.HM7.VStack.toString
String toString()
Definition: HM7.java:219
com.cliffc.aa.HM.HM7.Syntax.prep_lookup_deps
abstract void prep_lookup_deps(Ident id)
com.cliffc.aa.HM.HM7.T2.add_fld
void add_fld(String id, T2 fld, Worklist work)
Definition: HM7.java:783
com.cliffc.aa.HM.HM7.Syntax.p0
final SB p0(SB sb, VBitSet dups)
Definition: HM7.java:279
com.cliffc.aa.HM.HM7.parse
static Syntax parse(String s)
Definition: HM7.java:96
com.cliffc.aa.HM.HM7.Syntax.add_kids
abstract void add_kids(Worklist work)
com.cliffc.aa.HM.HM7.T2.toString
String toString()
Definition: HM7.java:1045
com.cliffc.aa.HM.HM7.VStack._nongen
final T2 _nongen
Definition: HM7.java:217
com.cliffc.aa.HM.HM7.Struct.add_kids
void add_kids(Worklist work)
Definition: HM7.java:563
com.cliffc.aa.util.Util
Definition: Util.java:5
com.cliffc.aa.HM.HM7.T2
Definition: HM7.java:621
com.cliffc.aa.HM.HM7.Ident.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM7.java:329
com.cliffc.aa.HM.HM7.Struct.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM7.java:564
com.cliffc.aa.HM.HM7.Syntax.hm
abstract boolean hm(Worklist work)
com.cliffc.aa.HM.HM7.T2.p
String p(VBitSet dups)
Definition: HM7.java:1085
com.cliffc.aa.HM.HM7.Lambda._targs
T2[] _targs
Definition: HM7.java:342
com.cliffc.aa.HM.HM7.VStack.Iter.hasNext
boolean hasNext()
Definition: HM7.java:236
com.cliffc.aa.HM.HM7.Let.Let
Let(String arg0, Syntax def, Syntax body)
Definition: HM7.java:409
com.cliffc.aa.HM.HM7.Ident.str
SB str(SB sb)
Definition: HM7.java:305
com.cliffc.aa.HM.HM7.T2._unify
boolean _unify(T2 that, Worklist work)
Definition: HM7.java:735
com.cliffc.aa.HM.HM7.Struct.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM7.java:574
com.cliffc.aa.HM.HM7.T2.is_nil
boolean is_nil()
Definition: HM7.java:664
com.cliffc.aa.HM.HM7.Syntax.debug_find
T2 debug_find()
Definition: HM7.java:250
com.cliffc.aa.HM.HM7.T2.nongen_in
boolean nongen_in(VStack syn)
Definition: HM7.java:946
com.cliffc.aa.type.TypeStr.con
static TypeStr con(String con)
Definition: TypeStr.java:42
com.cliffc.aa.HM.HM7.Con.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM7.java:298
com.cliffc.aa.HM.HM7.Worklist
Definition: HM7.java:200
com.cliffc.aa.HM.HM7.Con.p1
SB p1(SB sb)
Definition: HM7.java:292
com.cliffc.aa.HM.HM7.Struct
Definition: HM7.java:525
com.cliffc.aa.HM.HM7.T2.is_leaf
boolean is_leaf()
Definition: HM7.java:660
com.cliffc.aa.HM.HM7.T2._uid
final int _uid
Definition: HM7.java:623
com.cliffc.aa.HM.HM7.Let.str
SB str(SB sb)
Definition: HM7.java:410
com.cliffc.aa.HM.HM7.T2._cycle_equals
boolean _cycle_equals(T2 t)
Definition: HM7.java:968
com.cliffc.aa.HM.HM7.Struct.hm
boolean hm(Worklist work)
Definition: HM7.java:544
com.cliffc.aa.type.TypeStr
Definition: TypeStr.java:14
com.cliffc.aa.HM.HM7.Lambda
Definition: HM7.java:339
com.cliffc.aa.HM.HM7.T2.is_struct
boolean is_struct()
Definition: HM7.java:666
com.cliffc.aa.HM.HM7.Apply.str
SB str(SB sb)
Definition: HM7.java:445
com.cliffc.aa.HM.HM7.VStack.Iter.Iter
Iter()
Definition: HM7.java:235
com.cliffc.aa.HM.HM7.T2.VNAMES
static final HashMap< T2, Integer > VNAMES
Definition: HM7.java:1084
com.cliffc.aa.util.VBitSet
Definition: VBitSet.java:5
com.cliffc.aa.HM.HM7.Let.add_occurs
void add_occurs(Worklist work)
Definition: HM7.java:422
com.cliffc.aa.HM.HM7.T2._get_dups
VBitSet _get_dups(VBitSet visit, VBitSet dups)
Definition: HM7.java:1034
com.cliffc.aa.HM.HM7.Apply.is_if_nil
T2 is_if_nil()
Definition: HM7.java:519
NotNull
com.cliffc.aa.util.SB
Tight/tiny StringBuilder wrapper.
Definition: SB.java:8
com.cliffc.aa.type.Type.NIL
static final Type NIL
Definition: Type.java:332
com.cliffc.aa.HM.HM7.Ident.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM7.java:335
com.cliffc.aa.HM.HM7.X
static int X
Definition: HM7.java:93
com.cliffc.aa.HM.HM7.number
static Syntax number()
Definition: HM7.java:166
com.cliffc.aa.HM.HM7.T2.is_base
boolean is_base()
Definition: HM7.java:663
com.cliffc.aa.HM.HM7.Worklist._work
final HashSet< Syntax > _work
Definition: HM7.java:203
com.cliffc.aa.AA
an implementation of language AA
Definition: AA.java:9
com.cliffc.aa.HM.HM7.BUF
static byte[] BUF
Definition: HM7.java:94
com.cliffc.aa.HM.HM7.Ident._name
final String _name
Definition: HM7.java:303
com.cliffc.aa.HM.HM7.Apply.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM7.java:511
com.cliffc.aa.HM.HM7.T2.CNT
static int CNT
Definition: HM7.java:622
com.cliffc.aa.HM.HM7.Syntax._t
T2 _t
Definition: HM7.java:245
com.cliffc.aa.HM.HM7.Con
Definition: HM7.java:288
com.cliffc.aa.HM.HM7.Syntax.p2
abstract SB p2(SB sb, VBitSet dups)
com.cliffc.aa.HM.HM7.Lambda.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM7.java:388
com.cliffc.aa.HM.HM7.T2.occurs_in_type
boolean occurs_in_type(T2 x)
Definition: HM7.java:922
com.cliffc.aa.HM.HM7.Ident.add_kids
void add_kids(Worklist work)
Definition: HM7.java:321
com.cliffc.aa.HM.HM7.Lambda._body
final Syntax _body
Definition: HM7.java:341
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.util.SB.nl
SB nl()
Definition: SB.java:48
com.cliffc.aa.HM.HM7.T2.get_dups
VBitSet get_dups(VBitSet dups)
Definition: HM7.java:1033
com.cliffc.aa.HM.HM7.T2.add_deps_work
void add_deps_work(Worklist work)
Definition: HM7.java:1018
com.cliffc.aa.HM.HM7.Lambda.lookup
T2 lookup(String name)
Definition: HM7.java:378
com.cliffc.aa.HM.HM7.Con._con
final Type _con
Definition: HM7.java:289
com.cliffc.aa.HM.HM7.T2.push_update
void push_update(Syntax a)
Definition: HM7.java:1007
com.cliffc.aa.HM.HM7.Let.add_kids
void add_kids(Worklist work)
Definition: HM7.java:421
com.cliffc.aa.HM.HM7.T2.isa
boolean isa(String name)
Definition: HM7.java:662
com.cliffc.aa.HM.HM7.T2.or0
boolean or0(T2 that, Worklist work)
Definition: HM7.java:709
com.cliffc.aa.HM.HM7.isAlpha0
static boolean isAlpha0(byte c)
Definition: HM7.java:187
com.cliffc.aa.HM.HM7.Con.add_kids
void add_kids(Worklist work)
Definition: HM7.java:296
com.cliffc.aa.HM.HM7.Lambda.p2
SB p2(SB sb, VBitSet dups)
Definition: HM7.java:359
com.cliffc.aa.HM.HM7.Ident.hm
boolean hm(Worklist work)
Definition: HM7.java:308
com.cliffc.aa.HM.HM7.reset
static void reset()
Definition: HM7.java:89
com.cliffc.aa.util.SB.p
SB p(String s)
Definition: SB.java:13
com.cliffc.aa.HM.HM7.Field.p2
SB p2(SB sb, VBitSet dups)
Definition: HM7.java:591
com.cliffc.aa.HM.HM7.Let.more_work
boolean more_work(Worklist work)
Definition: HM7.java:435
com.cliffc.aa.HM.HM7.Field._str
final Syntax _str
Definition: HM7.java:587
com.cliffc.aa.HM.HM7.Struct._flds
final Syntax[] _flds
Definition: HM7.java:527
com.cliffc.aa.HM.HM7.T2._ids
String[] _ids
Definition: HM7.java:637
com.cliffc.aa.HM.HM7.T2.push_update_impl
void push_update_impl(Syntax a)
Definition: HM7.java:1008
com.cliffc.aa.HM.HM7.T2.VCNT
static int VCNT
Definition: HM7.java:1083
com.cliffc.aa.HM.HM7.T2.add_deps_work_impl
void add_deps_work_impl(Worklist work)
Definition: HM7.java:1019
com.cliffc.aa.HM.HM7.T2.fresh_unify
boolean fresh_unify(T2 that, VStack nongen, Worklist work)
Definition: HM7.java:819
com.cliffc.aa.HM.HM7.T2.unify
boolean unify(T2 that, Worklist work)
Definition: HM7.java:724
com.cliffc.aa.HM.HM7.Field.str
SB str(SB sb)
Definition: HM7.java:589
com.cliffc.aa.HM.HM7.T2._fresh
T2 _fresh(VStack nongen)
Definition: HM7.java:894
com.cliffc.aa.HM.HM7.Worklist.len
int len()
Definition: HM7.java:204
com.cliffc.aa.HM.HM7.T2.cycle_equals
boolean cycle_equals(T2 t)
Definition: HM7.java:962
com.cliffc.aa.HM.HM7.Worklist._ary
final Ary< Syntax > _ary
Definition: HM7.java:202
com.cliffc.aa.HM.HM7.T2._args
T2[] _args
Definition: HM7.java:631
com.cliffc.aa.HM.HM7.Con.Con
Con(Type con)
Definition: HM7.java:290
com.cliffc.aa.HM.HM7.T2._occurs_in
boolean _occurs_in(Syntax syn)
Definition: HM7.java:928
com.cliffc.aa.HM.HM7.Field.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM7.java:604
com.cliffc.aa.HM.HM7.Field._id
final String _id
Definition: HM7.java:586
com.cliffc.aa.HM.HM7.T2._fresh_unify
boolean _fresh_unify(T2 that, VStack nongen, Worklist work)
Definition: HM7.java:830
com.cliffc.aa.HM.HM7.Syntax.more_work_impl
final boolean more_work_impl(Worklist work)
Definition: HM7.java:270
com.cliffc.aa.HM.HM7.Con.str
SB str(SB sb)
Definition: HM7.java:291
com.cliffc.aa.HM.HM7.Lambda._args
final String[] _args
Definition: HM7.java:340
com.cliffc.aa.util.SB.i
SB i(int d)
Definition: SB.java:38
com.cliffc.aa.HM.HM7.VStack.Iter
Definition: HM7.java:233
com.cliffc.aa.HM.HM7.hm
static T2 hm(String sprog)
Definition: HM7.java:27
com.cliffc.aa.HM.HM7.Field.Field
Field(String id, Syntax str)
Definition: HM7.java:588
com.cliffc.aa.HM.HM7.Struct.p1
SB p1(SB sb)
Definition: HM7.java:538
com.cliffc.aa.HM.HM7.T2.DUPS
static final HashMap< Long, T2 > DUPS
Definition: HM7.java:723
com.cliffc.aa.HM.HM7.Let.p1
SB p1(SB sb)
Definition: HM7.java:411
com.cliffc.aa.HM.HM7.Struct.p2
SB p2(SB sb, VBitSet dups)
Definition: HM7.java:539
com.cliffc.aa.type.TypeMemPtr.STRPTR
static final TypeMemPtr STRPTR
Definition: TypeMemPtr.java:97
com.cliffc.aa.HM.HM7.Field.add_occurs
void add_occurs(Worklist work)
Definition: HM7.java:603
com.cliffc.aa.HM.HM7.Lambda.p1
SB p1(SB sb)
Definition: HM7.java:354
com.cliffc.aa.HM.HM7.Ident.add_occurs
void add_occurs(Worklist work)
Definition: HM7.java:322
com.cliffc.aa.HM.HM7.Let.targ
T2 targ()
Definition: HM7.java:413
com.cliffc.aa.HM.HM7.DEBUG_LEAKS
static boolean DEBUG_LEAKS
Definition: HM7.java:25
com.cliffc.aa.HM.HM7.Con.lookup
T2 lookup(String name)
Definition: HM7.java:295
com
com.cliffc.aa.HM.HM7.Ident.more_work
boolean more_work(Worklist work)
Definition: HM7.java:336
com.cliffc.aa.HM.HM7.T2.ODUPS
static final VBitSet ODUPS
Definition: HM7.java:913
com.cliffc.aa.HM.HM7.Let.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM7.java:425
com.cliffc.aa.HM.HM7.T2.str
static SB str(SB sb, VBitSet visit, T2 t, VBitSet dups)
Definition: HM7.java:1079
com.cliffc.aa.HM.HM7.Let._def
final Syntax _def
Definition: HM7.java:407
com.cliffc.aa.HM.HM7.isAlpha1
static boolean isAlpha1(byte c)
Definition: HM7.java:188
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.HM7.Struct.more_work
boolean more_work(Worklist work)
Definition: HM7.java:575
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.HM.HM7.Lambda.hm
boolean hm(Worklist work)
Definition: HM7.java:361
com.cliffc.aa.HM.HM7.Field.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM7.java:608
com.cliffc.aa.HM.HM7.T2.prim
static T2 prim(String name, T2... args)
Definition: HM7.java:648
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.HM.HM7.Ident.Ident
Ident(String name)
Definition: HM7.java:304
com.cliffc.aa.HM.HM7.Worklist.has
boolean has(Syntax s)
Definition: HM7.java:208
com.cliffc.aa.type.TypeFlt.FLT64
static final TypeFlt FLT64
Definition: TypeFlt.java:38
com.cliffc.aa.HM.HM7.VStack.Iter._vstk
VStack _vstk
Definition: HM7.java:234
com.cliffc.aa.HM.HM7.Syntax.lookup
abstract T2 lookup(String name)
com.cliffc.aa.HM.HM7.VStack
Definition: HM7.java:215
com.cliffc.aa.HM.HM7.Let.p2
SB p2(SB sb, VBitSet dups)
Definition: HM7.java:412
com.cliffc.aa.HM.HM7.require
static< T > T require(char c, T t)
Definition: HM7.java:189
com.cliffc.aa.HM.HM7.T2.make_leaf
static T2 make_leaf()
Definition: HM7.java:644
com.cliffc.aa.HM.HM7.Apply.lookup
T2 lookup(String name)
Definition: HM7.java:501