aa
HM.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 import static com.cliffc.aa.type.TypeFld.Access;
11 
12 // Combined Hindley-Milner and Global Constant Propagation typing.
13 
14 // Complete stand-alone, for research.
15 
16 // Treats HM as a Monotone Analysis Framework; converted to a worklist style.
17 // The type-vars are monotonically unified, gradually growing over time - and
18 // this is treated as the MAF lattice. Some of the normal Algo-W work gets
19 // done in a prepass; e.g. discovering identifier sources (SSA form), and
20 // building the non-generative set. Because of the non-local unification
21 // behavior type-vars include a "dependent Syntax" set; a set of Syntax
22 // elements put back on the worklist if this type unifies, beyond the expected
23 // parent and AST children.
24 //
25 // The normal HM unification steps are treated as the MAF transfer "functions",
26 // taking type-vars as inputs and producing new, unified, type-vars. Because
27 // unification happens in-place (normal Tarjan disjoint-set union), the xfer
28 // "functions" are executed for side-effects only, and return a progress flag.
29 // The transfer functions are virtual calls on each Syntax element. Some of
30 // the steps are empty because of the pre-pass (Let,Con).
31 
32 // HM Bases include anything from the GCP lattice, but 'widened' to form
33 // borders between e.g. ints and pointers. Includes polymorphic structures and
34 // fields (structural typing not duck typing), polymorphic nil-checking and an
35 // error type-var. Both HM and GCP types fully support recursive types.
36 //
37 // Unification typically makes many many temporary type-vars and immediately
38 // unifies them. For efficiency, this algorithm checks to see if unification
39 // requires an allocation first, instead of just "allocate and unify". The
40 // major place this happens is identifiers, which normally make a "fresh" copy
41 // of their type-var, then unify. I use a combined "make-fresh-and-unify"
42 // unification algorithm there. It is a structural clone of the normal unify,
43 // except that it lazily makes a fresh-copy of the left-hand-side on demand
44 // only; typically discovering that no fresh-copy is required.
45 //
46 // To engineer and debug the algorithm, the unification step includes a flag to
47 // mean "actually unify, and report a progress flag" vs "report if progress".
48 // The report-only mode is aggressively asserted for in the main loop; all
49 // Syntax elements that can make progress are asserted as on the worklist.
50 //
51 // GCP gets the normal MAF treatment, no surprises there.
52 //
53 // The combined algorithm includes transfer functions taking facts from both
54 // MAF lattices, producing results in the other lattice.
55 //
56 // For the GCP->HM direction, the HM 'if' has a custom transfer function
57 // instead of the usual one. Unification looks at the GCP value, and unifies
58 // either the true arm, or the false arm, or both or neither. In this way GCP
59 // allows HM to avoid picking up constraints from dead code.
60 //
61 // Also for GCP->HM, the HM ground terms or base terms include anything from
62 // the GCP lattice.
63 //
64 // For the HM->GCP direction, the GCP 'apply' has a customer transfer function
65 // where the result from a call gets lifted (JOINed) based on the matching GCP
66 // inputs - and the match comes from using the same HM type-var on both inputs
67 // and outputs. This allows e.g. "map" calls which typically merge many GCP
68 // values at many applies (call sites) and thus end up typed as a Scalar to
69 // Scalar, to improve the GCP type on a per-call-site basis.
70 //
71 // Test case 45 demonstrates this combined algorithm, with a program which can
72 // only be typed using the combination of GCP and HM.
73 //
74 // BNF for the "core AA" syntax:
75 // e = number | string | primitives | (fe0 fe1*) | { id* -> fe0 } | id | id = fe0; fe1 | @{ (label = fe0)* }
76 // fe = e | fe.label // optional field after expression
77 //
78 // BNF for the "core AA" pretty-printed types:
79 // T = X | X:T | { X* -> X } | base | @{ (label = X)* } | T? | Error
80 // base = any lattice element, all are nilable
81 // Multiple stacked T????s collapse
82 //
83 
84 public class HM {
85  // Mapping from primitive name to PrimSyn
86  static final HashMap<String,PrimSyn> PRIMSYNS = new HashMap<>();
87 
88  static final boolean DEBUG_LEAKS=false;
89  static { BitsAlias.init0(); BitsFun.init0(); }
90 
91  static final boolean DO_HM = true;
92  static final boolean DO_GCP = true;
93 
94  public static Root hm( String sprog ) {
95  Worklist work = new Worklist();
96  PrimSyn.WORK=work;
97 
98  for( PrimSyn prim : new PrimSyn[]{new If(), new Pair1(), new Pair(), new EQ(), new EQ0(), new Mul(), new Add(), new Dec(), new Str(), new Triple(), new Factor(), new IsEmpty(), new NotNil()} )
99  PRIMSYNS.put(prim.name(),prim);
100 
101  // Parse
102  Root prog = parse( sprog );
103 
104  // Prep for SSA: pre-gather all the (unique) ids
105  int cnt_syns = prog.prep_tree(null,null,work);
106  int init_T2s = T2.CNT;
107 
108  while( work.len()>0 ) { // While work
109  int oldcnt = T2.CNT; // Used for cost-check when no-progress
110  assert work._cnt<2000;
111  Syntax syn = work.pop(); // Get work
112  if( DO_HM ) {
113  T2 old = syn._hmt; // Old value for progress assert
114  if( syn.hm(work) ) {
115  assert !syn.debug_find().unify(old.find(),null);// monotonic: unifying with the result is no-progress
116  syn.add_hm_work(work); // Push affected neighbors on worklist
117  } else {
118  assert !DEBUG_LEAKS || oldcnt==T2.CNT; // No-progress consumes no-new-T2s
119  }
120  }
121  if( DO_GCP ) {
122  Type old = syn._flow;
123  Type t = syn.val(work);
124  if( t!=old ) { // Progress
125  assert old.isa(t); // Monotonic falling
126  syn._flow = t; // Update type
127  if( syn._par!=null ) { // Generally, parent needs revisit
128  work.push(syn._par); // Assume parent needs revisit
129  syn._par.add_val_work(syn,work); // Push affected neighbors on worklist
130  }
131  }
132  }
133 
134  // VERY EXPENSIVE ASSERT: O(n^2). Every Syntax that makes progress is on the worklist
135  assert prog.more_work(work);
136  }
137  assert prog.more_work(work);
138 
139  System.out.println("Initial T2s: "+init_T2s+", Prog size: "+cnt_syns+", worklist iters: "+work._cnt+", T2s: "+T2.CNT);
140  return prog;
141  }
142 
143  static void reset() {
146  PRIMSYNS.clear();
147  Pair1.PAIR1S.clear();
148  Lambda.FUNS.clear();
149  T2.reset();
150  PrimSyn.reset();
151  }
152 
153  // ---------------------------------------------------------------------
154  // Program text for parsing
155  private static int X;
156  private static byte[] BUF;
157  @Override public String toString() { return new String(BUF,X,BUF.length-X); }
158  static Root parse( String s ) {
159  X = 0;
160  BUF = s.getBytes();
161  Syntax prog = fterm();
162  if( skipWS() != -1 ) throw unimpl("Junk at end of program: "+new String(BUF,X,BUF.length-X));
163  // Inject IF at root
164  return new Root(prog);
165  }
166  static Syntax term() {
167  if( skipWS()==-1 ) return null;
168  if( isDigit(BUF[X]) ) return number();
169  if( BUF[X]=='"' ) return string();
170 
171  if( BUF[X]=='(' ) { // Parse an Apply
172  X++; // Skip paren
173  Syntax fun = fterm();
174  Ary<Syntax> args = new Ary<>(new Syntax[1],0);
175  while( skipWS()!= ')' && X<BUF.length ) args.push(fterm());
176  require(')');
177  // Guarding if-nil test inserts an upcast. This is a syntatic transform only.
178  if( fun instanceof If &&
179  args.at(0) instanceof Ident ) {
180  Ident id = (Ident)args.at(0);
181  args.set(1,new Apply(new Lambda(args.at(1), id._name),
182  new Apply(new NotNil(),new Ident(id._name))));
183  }
184  return new Apply(fun,args.asAry());
185  }
186 
187  if( BUF[X]=='{' ) { // Lambda of 1 or 2 args
188  X++; // Skip paren
189  Ary<String> args = new Ary<>(new String[1],0);
190  while( skipWS()!='-' ) args.push(id());
191  require("->");
192  Syntax body = fterm();
193  require('}');
194  return new Lambda(body,args.asAry());
195  }
196  // Let or Id
197  if( isAlpha0(BUF[X]) ) {
198  String id = id();
199  if( skipWS()!='=' ) {
200  PrimSyn prim = PRIMSYNS.get(id); // No shadowing primitives or this lookup returns the prim instead of the shadow
201  return prim==null ? new Ident(id) : prim.make(); // Make a prim copy with fresh HM variables
202  }
203  // Let expression; "id = term(); term..."
204  X++; // Skip '='
205  Syntax def = fterm();
206  require(';');
207  return new Let(id,def,fterm());
208  }
209 
210  // Structure
211  if( BUF[X]=='@' ) {
212  X++;
213  require('{');
214  Ary<String> ids = new Ary<>(String.class);
215  Ary<Syntax> flds = new Ary<>(Syntax.class);
216  while( skipWS()!='}' && X < BUF.length ) {
217  String id = require('=',id());
218  Syntax fld = fterm();
219  if( fld==null ) throw unimpl("Missing term for field "+id);
220  ids .push( id);
221  flds.push(fld);
222  if( skipWS()==',' ) X++;
223  }
224  require('}');
225  return new Struct(ids.asAry(),flds.asAry());
226  }
227 
228  throw unimpl("Unknown syntax");
229  }
230  // Parse a term with an optional following field.
231  private static Syntax fterm() {
232  Syntax term=term();
233  while( true ) {
234  if( term==null || skipWS()!='.' ) return term;
235  X++;
236  term = new Field(id(),term);
237  }
238  }
239  private static final SB ID = new SB();
240  private static String id() {
241  ID.clear();
242  while( X<BUF.length && isAlpha1(BUF[X]) )
243  ID.p((char)BUF[X++]);
244  String s = ID.toString().intern();
245  if( s.length()==0 ) throw unimpl("Missing id");
246  return s;
247  }
248  private static Syntax number() {
249  if( BUF[X]=='0' ) { X++; return new Con(Type.XNIL); }
250  int sum=0;
251  while( X<BUF.length && isDigit(BUF[X]) )
252  sum = sum*10+BUF[X++]-'0';
253  if( X>= BUF.length || BUF[X]!='.' )
254  return new Con(TypeInt.con(sum));
255  // Ambiguous '.' in: 2.3 vs 2.x (field load from a number)
256  if( X+1<BUF.length && isAlpha0(BUF[X+1]) )
257  return new Con(TypeInt.con(sum));
258  X++;
259  float f = (float)sum;
260  f = f + (BUF[X++]-'0')/10.0f;
261  return new Con(TypeFlt.con(f));
262  }
263  private static Syntax string() {
264  int start = ++X;
265  while( X<BUF.length && BUF[X]!='"' ) X++;
266  return require('"', new Con(TypeMemPtr.make(BitsAlias.STRBITS,TypeStr.con(new String(BUF,start,X-start).intern()))));
267  }
268  private static byte skipWS() {
269  while( X<BUF.length && isWS(BUF[X]) ) X++;
270  return X==BUF.length ? -1 : BUF[X];
271  }
272  private static boolean isWS (byte c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; }
273  private static boolean isDigit (byte c) { return '0' <= c && c <= '9'; }
274  private static boolean isAlpha0(byte c) { return ('a'<=c && c <= 'z') || ('A'<=c && c <= 'Z') || (c=='_') || (c=='*') || (c=='?') || (c=='+'); }
275  private static boolean isAlpha1(byte c) { return isAlpha0(c) || ('0'<=c && c <= '9') || (c=='/'); }
276  private static void require(char c) { if( skipWS()!=c ) throw unimpl("Missing '"+c+"'"); X++; }
277  private static <T> T require(char c, T t) { require(c); return t; }
278  private static void require(String s) {
279  skipWS();
280  for( int i=0; i<s.length(); i++ )
281  if( X+i >= BUF.length || BUF[X+i]!=s.charAt(i) )
282  throw unimpl("Missing '"+s+"'");
283  X+=s.length();
284  }
285 
286  // ---------------------------------------------------------------------
287  // Worklist of Syntax nodes
288  private static class Worklist {
289  public int _cnt; // Count of items ever popped (not the current length)
290  private final Ary<Syntax> _ary = new Ary<>(Syntax.class); // For picking random element
291  private final HashSet<Syntax> _work = new HashSet<>(); // For preventing dups
292  public int len() { return _ary.len(); }
293  public void push(Syntax s) { if( s!=null && !_work.contains(s) ) _work.add(_ary.push(s)); }
294  public Syntax pop() { Syntax s = _ary.pop();_cnt++; _work.remove(s); return s; }
295  //public Syntax pop() { Syntax s = _ary.del( _cnt++%_ary._len); _work.remove(s); return s; }
296  public boolean has(Syntax s) { return _work.contains(s); }
297  public void addAll(Ary<? extends Syntax> ss) { if( ss != null ) for( Syntax s : ss ) push(s); }
298  public void clear() {
299  _cnt=0;
300  _ary.clear();
301  _work.clear();
302  }
303  @Override public String toString() { return _ary.toString(); }
304  }
305 
306  // ---------------------------------------------------------------------
307  // Small classic tree of T2s, immutable, with sharing at the root parts.
308  static class VStack implements Iterable<T2> {
309  final VStack _par;
310  private T2 _nongen;
311  final int _d;
312  VStack( VStack par, T2 nongen ) { _par=par; _nongen=nongen; _d = par==null ? 0 : par._d+1; }
313  T2 nongen() {
314  T2 n = _nongen.find();
315  return n==_nongen ? n : (_nongen=n);
316  }
317  @Override public String toString() {
318  // Collect dups across the forest of types
319  VBitSet dups = new VBitSet();
320  for( VStack vs = this; vs!=null; vs = vs._par )
321  vs._nongen.get_dups(dups);
322  // Now recursively print
323  return str(new SB(),dups).toString();
324  }
325  SB str(SB sb, VBitSet dups) {
326  _nongen.str(sb,new VBitSet(),dups);
327  if( _par!=null ) _par.str(sb.p(" , "),dups);
328  return sb;
329  }
330  @NotNull @Override public Iterator<T2> iterator() { return new Iter(); }
331  private class Iter implements Iterator<T2> {
332  private VStack _vstk;
333  Iter() { _vstk=VStack.this; }
334  @Override public boolean hasNext() { return _vstk!=null; }
335  @Override public T2 next() { T2 v = _vstk.nongen(); _vstk = _vstk._par; return v; }
336  }
337  }
338 
339  // ---------------------------------------------------------------------
340  static abstract class Syntax {
341  Syntax _par; // Parent in the AST
342  VStack _nongen; // Non-generative type variables
343  T2 _hmt; // Current HM type
344  T2 find() { // U-F find
345  T2 t = _hmt.find();
346  return t== _hmt ? t : (_hmt =t);
347  }
348  T2 debug_find() { return _hmt.debug_find(); } // Find, without the roll-up
349 
350  // Dataflow types. Varies during a run of GCP.
352 
353  // Compute a new HM type.
354  // If no change, return false.
355  // If a change, return always true, however:
356  // - If 'work' is null do not change/set anything.
357  // - If 'work' is available, update the worklist.
358  abstract boolean hm(Worklist work);
359 
360  abstract void add_hm_work(Worklist work); // Add affected neighbors to worklist
361 
362  // Compute and return (and do not set) a new GCP type for this syntax.
363  abstract Type val(Worklist work);
364 
365  void add_val_work(Syntax child, Worklist work) {} // Add affected neighbors to worklist
366 
367  // First pass to "prepare" the tree; does e.g. Ident lookup, sets initial
368  // type-vars and counts tree size.
369  abstract int prep_tree(Syntax par, VStack nongen, Worklist work);
370  final void prep_tree_impl( Syntax par, VStack nongen, Worklist work, T2 t ) {
371  _par = par;
372  _hmt = t;
373  _flow= Type.XSCALAR;
374  _nongen = nongen;
375  work.push(this);
376  }
378 
379  // Giant Assert: True if OK; all Syntaxs off worklist do not make progress
380  abstract boolean more_work(Worklist work);
381  final boolean more_work_impl(Worklist work) {
382  if( work.has(this) ) return true;
383  if( DO_HM && hm(null) ) // Any more HM work?
384  return false; // Found HM work not on worklist
385  if( DO_GCP && val(null)!=_flow )
386  return false; // Found GCP work not on worklist
387  return true;
388  }
389  // Print for debugger
390  @Override final public String toString() { return str(new SB()).toString(); }
391  abstract SB str(SB sb);
392  // Line-by-line print with more detail
393  public String p() { return p0(new SB(), new VBitSet()).toString(); }
394  final SB p0(SB sb, VBitSet dups) {
395  _hmt.get_dups(dups);
396  VBitSet visit = new VBitSet();
397  p1(sb.i());
398  if( DO_HM ) _hmt .str(sb.p(", HM="), visit,dups);
399  if( DO_GCP ) _flow.str(sb.p(", CCP="),visit.clr(),null,false);
400  sb.nl();
401  return p2(sb.ii(1),dups).di(1);
402  }
403  abstract SB p1(SB sb); // Self short print
404  abstract SB p2(SB sb, VBitSet dups); // Recursion print
405  }
406 
407  static class Con extends Syntax {
408  final Type _con;
409  Con(Type con) { super(); _con=con; }
410  @Override SB str(SB sb) { return p1(sb); }
411  @Override SB p1(SB sb) { return sb.p(_con.toString()); }
412  @Override SB p2(SB sb, VBitSet dups) { return sb; }
413  @Override boolean hm(Worklist work) { return false; }
414  @Override Type val(Worklist work) { return _con; }
415  @Override void add_hm_work(Worklist work) { }
416  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
417  // A '0' turns into a nilable leaf.
418  T2 base = _con==Type.XNIL ? T2.make_nil(T2.make_leaf()) : T2.make_base(_con);
419  prep_tree_impl(par, nongen, work, base);
420  return 1;
421  }
422  @Override boolean more_work(Worklist work) { return more_work_impl(work); }
423  }
424 
425 
426  static class Ident extends Syntax {
427  final String _name; // The identifier name
428  Syntax _def; // Cached syntax defining point
429  int _idx; // Index in Lambda (which arg of many)
430  T2 _idt; // Cached type var for the name in scope
431  Ident(String name) { _name=name; }
432  @Override SB str(SB sb) { return p1(sb); }
433  @Override SB p1(SB sb) { return sb.p(_name); }
434  @Override SB p2(SB sb, VBitSet dups) { return sb; }
435  T2 idt() {
436  T2 idt = _idt.find();
437  return idt==_idt ? idt : (_idt=idt);
438  }
439  @Override boolean hm(Worklist work) {
440  return idt().fresh_unify(find(),_nongen,work);
441  }
442  @Override void add_hm_work(Worklist work) {
443  work.push(_par);
444  T2 t = idt();
445  if( t.nongen_in(_par == null ? null : _par._nongen) ) // Got captured in some parent?
446  t.add_deps_work(work); // Need to revisit dependent ids
447  if( _par instanceof Apply && ((Apply)_par)._fun instanceof NotNil )
448  work.push(((Apply)_par)._fun);
449  }
450  @Override Type val(Worklist work) {
451  return _def instanceof Let ? ((Let)_def)._def._flow : ((Lambda)_def)._types[_idx];
452  }
453  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
454  prep_tree_impl(par,nongen,work,T2.make_leaf());
455  for( Syntax syn = _par; syn!=null; syn = syn._par )
456  syn.prep_lookup_deps(this);
457 
458  // Lookup, and get the T2 type var and a pointer to the flow type.
459  for( Syntax syn = _par; syn!=null; syn = syn._par ) {
460  if( syn instanceof Lambda ) {
461  Lambda lam = (Lambda)syn;
462  if( (_idx = Util.find(lam._args,_name)) != -1 )
463  return _init(lam,lam.targ(_idx));
464  } else if( syn instanceof Let ) {
465  Let let = (Let)syn; _idx=-1;
466  if( Util.eq(let._arg0,_name) )
467  return _init(let,let._targ);
468  }
469  }
470  throw new RuntimeException("Parse error, "+_name+" is undefined in "+_par);
471  }
472  private int _init(Syntax def,T2 idt) { _def = def; _idt = idt; return 1; }
473  @Override boolean more_work(Worklist work) { return more_work_impl(work); }
474  }
475 
476 
477  static class Lambda extends Syntax {
478  // Map from FIDXs to Lambdas
480  final String[] _args;
481  final Syntax _body;
482  final T2[] _targs;
483  final Type[] _types;
484  final int _fidx;
485 
486  Lambda(Syntax body, String... args) {
487  _args=args;
488  _body=body;
489  // Type variables for all arguments
490  _targs = new T2[args.length];
491  for( int i=0; i<args.length; i++ ) _targs[i] = T2.make_leaf();
492  // Flow types for all arguments
493  _types = new Type[args.length];
494  for( int i=0; i<args.length; i++ ) _types[i] = Type.XSCALAR;
495  // A unique FIDX for this Lambda
496  _fidx = BitsFun.new_fidx();
497  FUNS.put(_fidx,this);
498  _flow = val(null);
499  }
500  @Override SB str(SB sb) {
501  sb.p("{ ");
502  for( String arg : _args ) sb.p(arg).p(' ');
503  return _body.str(sb.p("-> ")).p(" }");
504  }
505  @Override SB p1(SB sb) {
506  sb.p("{ ");
507  for( int i=0; i<_args.length; i++ ) {
508  sb.p(_args[i]);
509  if( DO_HM ) sb.p(", HM=" ).p(targ(i).toString());
510  if( DO_GCP ) sb.p(", CCP=").p(_types[i]);
511  sb.nl().i().p(" ");
512  }
513  return sb.p(" -> ... } ");
514  }
515  @Override SB p2(SB sb, VBitSet dups) { return _body.p0(sb,dups); }
516  T2 targ(int i) { T2 targ = _targs[i].find(); return targ==_targs[i] ? targ : (_targs[i]=targ); }
517  @Override boolean hm(Worklist work) {
518  boolean progress = false;
519  // The normal lambda work
520  T2 old = find();
521  if( old.is_err() ) return false;
522  if( old.is_fun() ) { // Already a function? Compare-by-parts
523  for( int i=0; i<_targs.length; i++ )
524  if( old.args(i).unify(targ(i),work) )
525  { progress=true; break; }
526  if( !progress && !old.args(_targs.length).unify(_body.find(),work) )
527  return false; // Shortcut: no progress, no allocation
528  }
529  // Make a new T2 for progress
530  T2[] targs = Arrays.copyOf(_targs,_targs.length+1);
531  targs[_targs.length] = _body.find();
532  T2 fun = T2.make_fun(BitsFun.make0(_fidx),targs);
533  return old.unify(fun,work);
534  }
535  @Override void add_hm_work(Worklist work) {
536  work.push(_par );
537  work.push(_body);
538  for( int i=0; i<_targs.length; i++ )
539  if( targ(i).occurs_in_type(find()) ) work.addAll(targ(i)._deps);
540  }
541  @Override Type val(Worklist work) { return TypeFunPtr.make(_fidx,_args.length,Type.ANY); }
542  // Ignore arguments, and return body type. Very conservative.
543  Type apply(Syntax[] args) { return _body._flow; }
544  @Override void add_val_work(Syntax child, Worklist work) {
545  // Body changed, all Apply sites need to recompute
546  work.addAll(find()._deps);
547  }
548  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
549  prep_tree_impl(par,nongen,work,T2.make_leaf());
550  VStack vs = nongen;
551  for( T2 targ : _targs ) vs = new VStack(vs, targ);
552  return _body.prep_tree(this,vs,work) + 1;
553  }
554  @Override void prep_lookup_deps(Ident id) {
555  for( int i=0; i<_args.length; i++ )
556  if( Util.eq(_args[i],id._name) ) _targs[i].push_update(id);
557  }
558  @Override boolean more_work(Worklist work) {
559  if( !more_work_impl(work) ) return false;
560  return _body.more_work(work);
561  }
562  }
563 
564  static class Let extends Syntax {
565  final String _arg0;
566  final Syntax _def, _body;
568  Let(String arg0, Syntax def, Syntax body) { _arg0=arg0; _body=body; _def=def; _targ=T2.make_leaf(); }
569  @Override SB str(SB sb) { return _body.str(_def.str(sb.p(_arg0).p(" = ")).p("; ")); }
570  @Override SB p1(SB sb) { return sb.p(_arg0).p(" = ... ; ..."); }
571  @Override SB p2(SB sb, VBitSet dups) { _def.p0(sb,dups); return _body.p0(sb,dups); }
572  @Override boolean hm(Worklist work) { return false; }
573  @Override void add_hm_work(Worklist work) {
574  work.push(_par);
575  work.push(_body);
576  work.push(_def);
577  work.addAll(_def.find()._deps);
578  }
579  @Override Type val(Worklist work) { return _body._flow; }
580  @Override void add_val_work(Syntax child, Worklist work) {
581  if( child==_def )
582  work.addAll(_def.find()._deps);
583  }
584 
585  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
586  prep_tree_impl(par,nongen,work,_body._hmt);
587  int cnt = _body.prep_tree(this, nongen ,work) +
588  _def .prep_tree(this,new VStack(nongen,_targ),work);
589  _hmt = _body._hmt; // Unify 'Let._hmt' with the '_body'
590  _targ.unify(_def.find(),work);
591  return cnt+1;
592  }
593  @Override void prep_lookup_deps(Ident id) {
594  if( Util.eq(id._name,_arg0) ) _targ.push_update(id);
595  }
596  @Override boolean more_work(Worklist work) {
597  if( !more_work_impl(work) ) return false;
598  return _body.more_work(work) && _def.more_work(work);
599  }
600  }
601 
602  static class Apply extends Syntax {
603  final Syntax _fun;
604  final Syntax[] _args;
605  Apply(Syntax fun, Syntax... args) { _fun = fun; _args = args; }
606  @Override SB str(SB sb) {
607  _fun.str(sb.p("(")).p(" ");
608  for( Syntax arg : _args )
609  arg.str(sb).p(" ");
610  return sb.unchar().p(")");
611  }
612  @Override SB p1(SB sb) { return sb.p("(...)"); }
613  @Override SB p2(SB sb, VBitSet dups) {
614  _fun.p0(sb,dups);
615  for( Syntax arg : _args ) arg.p0(sb,dups);
616  return sb;
617  }
618 
619  // Unifiying these: make_fun(this.arg0 this.arg1 -> new )
620  // _fun{_fun.arg0 _fun.arg1 -> _fun.rez}
621  @Override boolean hm(Worklist work) {
622  boolean progress = false;
623 
624  // Progress if:
625  // _fun is not a function
626  // any arg-pair-unifies make progress
627  // this-unify-_fun.return makes progress
628  T2 tfun = _fun.find();
629  if( !tfun.is_fun() ) { // Not a function, so progress
630  if( tfun.is_err() ) return find().unify(tfun,work);
631  if( work==null ) return true; // Will-progress & just-testing
632  T2[] targs = new T2[_args.length+1];
633  for( int i=0; i<_args.length; i++ )
634  targs[i] = _args[i].find();
635  targs[_args.length] = find(); // Return
636  T2 nfun = T2.make_fun(BitsFun.FULL,targs);
637  progress = tfun.unify(nfun,work);
638  return tfun.find().is_err() ? find().unify(tfun.find(),work) : progress;
639  }
640 
641  if( tfun._args.length != _args.length+1 )
642  progress = T2.make_err("Mismatched argument lengths").unify(find(), work);
643  // Check for progress amongst arg pairs
644  for( int i=0; i<_args.length; i++ ) {
645  progress |= tfun.args(i).unify(_args[i].find(),work);
646  if( progress && work==null ) return true; // Will-progress & just-testing early exit
647  if( (tfun=tfun.find()).is_err() ) return find().unify(tfun,work);
648  }
649  // Check for progress on the return
650  progress |= tfun.args(_args.length).unify(find(),work);
651  if( (tfun=tfun.find()).is_err() ) return find().unify(tfun,work);
652 
653  return progress;
654  }
655  @Override void add_hm_work(Worklist work) {
656  work.push(_par);
657  for( Syntax arg : _args ) work.push(arg);
658  }
659  static private final HashMap<T2,Type> T2MAP = new HashMap<>();
661  @Override Type val(Worklist work) {
662  Type flow = _fun._flow;
663  if( flow.above_center() ) return Type.XSCALAR;
664  if( !(flow instanceof TypeFunPtr) ) return Type.SCALAR;
665  TypeFunPtr tfp = (TypeFunPtr)flow;
666  // Have some functions, meet over their returns.
667  Type rez = Type.XSCALAR;
668  if( tfp._fidxs==BitsFun.FULL ) rez = Type.SCALAR;
669  else
670  for( int fidx : tfp._fidxs )
671  rez = rez.meet(Lambda.FUNS.get(fidx).apply(_args));
672  if( rez==Type.XSCALAR ) // Fast path cutout, no improvement possible
673  return rez;
674 
675  // Attempt to lift the result, based on HM types. Walk the input HM type
676  // and CCP flow type in parallel and create a mapping. Then walk the
677  // output HM type and CCP flow type in parallel, and join output CCP
678  // types with the matching input CCP type.
679  if( DO_HM ) {
680  T2MAP.clear(); WDUPS.clear();
681  // Walk the inputs, building a mapping
683  for( Syntax arg : _args )
684  { WDUPS.clear(); arg.find().walk_types_in(arg._flow); }
685  // Walk the outputs, building an improved result
686  Type rez2 = find().walk_types_out(rez);
687  rez = rez2.join(rez); // Lift result
688  if( !_flow.isa(rez) )
689  rez = _flow; // TODO: Cheaty force monotonic
690  }
691  return rez;
692  }
693  @Override void add_val_work(Syntax child, Worklist work) {
694  // If function changes type, recompute self
695  if( child==_fun ) work.push(this);
696  // If an argument changes type, adjust the lambda arg types
697  Type flow = _fun._flow;
698  if( flow.above_center() ) return;
699  if( !(flow instanceof TypeFunPtr) ) return;
700  // Meet the actuals over the formals.
701  for( int fidx : ((TypeFunPtr)flow)._fidxs ) {
702  Lambda fun = Lambda.FUNS.get(fidx);
703  if( fun!=null ) {
704  fun.find().push_update(this); // Discovered as call-site; if the Lambda changes the Apply needs to be revisited.
705  for( int i=0; i<fun._types.length; i++ ) {
706  Type formal = fun._types[i];
707  Type actual = this instanceof Root ? Root.widen(fun.targ(i)) : _args[i]._flow;
708  Type rez = formal.meet(actual);
709  if( formal != rez ) {
710  fun._types[i] = rez;
711  work.addAll(fun.targ(i)._deps);
712  work.push(fun._body);
713  if( i==0 && fun instanceof If ) work.push(fun); // Specifically If might need more unification
714  }
715  }
716  }
717  }
718  }
719 
720  @Override int prep_tree(Syntax par, VStack nongen, Worklist work) {
721  prep_tree_impl(par,nongen,work,T2.make_leaf());
722  int cnt = 1+_fun.prep_tree(this,nongen,work);
723  for( Syntax arg : _args ) cnt += arg.prep_tree(this,nongen,work);
724  return cnt;
725  }
726  @Override boolean more_work(Worklist work) {
727  if( !more_work_impl(work) ) return false;
728  if( !_fun.more_work(work) ) return false;
729  for( Syntax arg : _args ) if( !arg.more_work(work) ) return false;
730  return true;
731  }
732  }
733 
734 
735  static class Root extends Apply {
736  static final Syntax[] NARGS = new Syntax[0];
737  Root(Syntax body) { super(body); }
738  @Override SB str(SB sb) { return _fun.str(sb); }
739  @Override boolean hm(Worklist work) { return find().unify(_fun.find(),work); }
740  @Override void add_hm_work(Worklist work) { }
741  // Root-widening is when Root acts as-if it is calling the returned
742  // function with the worse-case legal args.
743  static Type widen(T2 t2) { return t2.as_flow(); }
744  @Override Type val(Worklist work) {
745  if( _fun._flow.above_center() || work==null )
746  return _fun._flow;
747  // Root-widening needs to call all functions which can be returned from
748  // the Root or from any function reachable from the Root via struct &
749  // fields, or by being returned from another function.
750  BitsFun fidxs = find().find_fidxs();
751  if( fidxs != BitsFun.EMPTY )
752  for( int fidx : fidxs ) {
753  Lambda fun = Lambda.FUNS.get(fidx);
754  if( fun!=null ) {
755  fun.find().push_update(this); // Discovered as call-site; if the Lambda changes the Apply needs to be revisited.
756  // For each returned function, assume Root calls all arguments with
757  // worse-case values.
758  for( int i=0; i<fun._types.length; i++ ) {
759  Type formal = fun._types[i];
760  Type actual = Root.widen(fun.targ(i));
761  Type rez = formal.meet(actual);
762  if( formal != rez ) {
763  fun._types[i] = rez;
764  work.addAll(fun.targ(i)._deps);
765  work.push(fun._body);
766  }
767  }
768  }
769  }
770 
771  return _fun._flow;
772  }
773 
774  // Expand functions to full signatures, recursively
775  Type flow_type() { return add_sig(_flow); }
776  private static Type add_sig(Type t) {
777  if( t instanceof TypeFunPtr ) {
778  TypeFunPtr fun = (TypeFunPtr)t;
779  Type rez = Type.XSCALAR;
780  for( int fidx : fun._fidxs )
781  rez = rez.meet(Lambda.FUNS.get(fidx).apply(NARGS));
782  Type rez2 = add_sig(rez);
784  } else {
785  return t;
786  }
787  }
788  }
789 
790 
791  // Structure or Records.
792  static class Struct extends Syntax {
793  final int _alias;
794  final String[] _ids;
795  final Syntax[] _flds;
796  Struct( String[] ids, Syntax[] flds ) {
797  _ids=ids;
798  _flds=flds;
799  // Make a TMP
801  }
802  @Override SB str(SB sb) {
803  sb.p("@{").p(_alias);
804  for( int i=0; i<_ids.length; i++ ) {
805  sb.p(' ').p(_ids[i]).p(" = ");
806  _flds[i].str(sb);
807  if( i < _ids.length-1 ) sb.p(',');
808  }
809  return sb.p("}");
810  }
811  @Override SB p1(SB sb) { return sb.p("@{").p(_alias).p(" ... } "); }
812  @Override SB p2(SB sb, VBitSet dups) {
813  for( int i=0; i<_ids.length; i++ )
814  _flds[i].p0(sb.i().p(_ids[i]).p(" = ").nl(),dups);
815  return sb;
816  }
817  @Override boolean hm(Worklist work) {
818  boolean progress = false, must_alloc=false;
819 
820  // Force result to be a struct with at least these fields.
821  // Do not allocate a T2 unless we need to pick up fields.
822  T2 rec = find();
823  if( rec.is_err() ) return false;
824  for( String id : _ids )
825  if( Util.find(rec._ids, id) == -1 )
826  { must_alloc = true; break; }
827  if( must_alloc ) { // Must allocate.
828  if( work==null ) return true; // Will progress
829  T2[] t2s = new T2[_ids.length];
830  for( int i=0; i<_ids.length; i++ )
831  t2s[i] = _flds[i].find();
832  T2.make_struct(BitsAlias.make0(_alias),_ids,t2s).unify(rec,work);
833  rec=find();
834  progress = true;
835  }
836 
837  // Extra fields are unified with ERR since they are not created here:
838  // error to load from a non-existing field
839  for( int i=0; i<rec._ids.length; i++ ) {
840  if( Util.find(_ids,rec._ids[i])== -1 && !rec.args(i).is_err() ) {
841  if( work==null ) return true;
842  progress |= rec.args(i).unify(find().miss_field(rec._ids[i]),work);
843  }
844  }
845 
846  // Unify existing fields. Ignore extras on either side.
847  for( int i=0; i<_ids.length; i++ ) {
848  int idx = Util.find(rec._ids,_ids[i]);
849  if( idx!= -1 ) progress |= rec.args(idx).unify(_flds[i].find(),work);
850  if( work==null && progress ) return true;
851  }
852  rec.push_update(this);
853 
854  return progress;
855  }
856  @Override void add_hm_work(Worklist work) {
857  work.push(_par);
858  for( Syntax fld : _flds ) work.push(fld);
859  }
860  @Override Type val(Worklist work) {
861  TypeFld[] ts = TypeFlds.get(_flds.length+1);
862  ts[0] = TypeFld.NO_DISP;
863  for( int i=0; i<_flds.length; i++ )
864  ts[i+1] = TypeFld.make(_ids[i],_flds[i]._flow,Access.Final,i+1);
865  TypeStruct tstr = TypeStruct.make(ts);
866  TypeStruct t2 = tstr.approx(1,_alias);
867  return TypeMemPtr.make(_alias,t2);
868  }
869 
870  @Override int prep_tree(Syntax par, VStack nongen, Worklist work) {
871  T2[] t2s = new T2[_ids.length];
872  prep_tree_impl(par, nongen, work, T2.make_struct(BitsAlias.make0(_alias),_ids,t2s));
873  int cnt = 1; // One for self
874  for( int i=0; i<_flds.length; i++ ) { // Prep all sub-fields
875  cnt += _flds[i].prep_tree(this,nongen,work);
876  t2s[i] = _flds[i].find();
877  }
878  return cnt;
879  }
880  @Override boolean more_work(Worklist work) {
881  if( !more_work_impl(work) ) return false;
882  for( Syntax fld : _flds )
883  if( !fld.more_work(work) )
884  return false;
885  return true;
886  }
887  }
888 
889  // Field lookup in a Struct
890  static class Field extends Syntax {
891  final String _id;
892  final Syntax _rec;
893  Field( String id, Syntax str ) { _id=id; _rec =str; }
894  @Override SB str(SB sb) { return _rec.str(sb).p(".").p(_id); }
895  @Override SB p1 (SB sb) { return sb.p(".").p(_id); }
896  @Override SB p2(SB sb, VBitSet dups) { return _rec.p0(sb,dups); }
897  @Override boolean hm(Worklist work) {
898  if( find().is_err() ) return false; // Already an error; no progress
899  T2 rec = _rec.find();
900  if( rec.is_nilable() || (rec._alias!=null && rec._alias.test(0)) )
901  return find().unify(T2.make_err("May be nil when loading field "+_id),work);
902  rec.push_update(this);
903  int idx = rec._ids==null ? -1 : Util.find(rec._ids,_id);
904  if( idx!= -1 ) // Unify against a pre-existing field
905  return rec.args(idx).unify(find(), work);
906  // The remaining cases all make progress and return true
907  if( work==null ) return true;
908  if( rec.is_err() ) return find().unify(rec,work);
909  // Not a struct or no field, force it to be one
910  if( rec.is_struct() && rec._open ) // Effectively unify with an extended struct.
911  return rec.add_fld(_id,find(),work);
912  if( rec.is_leaf() )
913  return T2.make_struct(BitsAlias.EMPTY,new String[]{_id}, new T2[]{find().push_update(rec._deps)},true).unify(rec, work);
914 
915  return find().unify(rec.miss_field(_id),work);
916  }
917  @Override void add_hm_work(Worklist work) {
918  work.push(_par);
919  work.push(_rec);
920  _rec.add_hm_work(work);
921  }
922  @Override Type val(Worklist work) {
923  Type trec = _rec._flow;
924  if( trec.above_center() ) return Type.XSCALAR;
925  if( trec instanceof TypeMemPtr ) {
926  TypeMemPtr tmp = (TypeMemPtr)trec;
927  if( tmp._obj instanceof TypeStruct ) {
928  TypeStruct tstr = (TypeStruct)tmp._obj;
929  int idx = tstr.fld_find(_id);
930  if( idx!=-1 ) return tstr.at(idx); // Field type
931  }
932  if( tmp._obj.above_center() ) return Type.XSCALAR;
933  }
934  // TODO: Need an error type here
935  return Type.SCALAR;
936  }
937  @Override int prep_tree(Syntax par, VStack nongen, Worklist work) {
938  prep_tree_impl(par, nongen, work, T2.make_leaf());
939  return _rec.prep_tree(this,nongen,work)+1;
940  }
941  @Override boolean more_work(Worklist work) {
942  if( !more_work_impl(work) ) return false;
943  return _rec.more_work(work);
944  }
945  }
946 
947 
948  abstract static class PrimSyn extends Lambda implements Cloneable {
949  static T2 BOOL, INT64, FLT64, STRP;
950  static Worklist WORK;
952  static void reset() {
959  }
960  abstract String name();
961  private static final String[][] IDS = new String[][] {
962  null,
963  {"x"},
964  {"x","y"},
965  {"x","y","z"},
966  };
967  PrimSyn(T2 ...t2s) {
968  super(null,IDS[t2s.length-1]);
969  _hmt = T2.make_fun(BitsFun.make0(_fidx),t2s).fresh();
970  for( int i=0; i<_targs.length; i++ )
971  _targs[i] = _hmt.args(i).push_update(this);
972  }
973  abstract PrimSyn make();
974  @Override int prep_tree(Syntax par, VStack nongen, Worklist work) {
975  prep_tree_impl(par,nongen,work, _hmt);
976  return 1;
977  }
978  @Override boolean hm(Worklist work) {
979  T2 old = find();
980  if( old.is_err() ) return false;
981  assert old.is_fun();
982  for( int i=0; i<_targs.length; i++ )
983  if( targ(i).is_err() )
984  return old.unify(targ(i),work);
985 
986  return false;
987  }
988  @Override void add_hm_work(Worklist work) {
989  if( find().is_err() ) work.push(_par);
990  }
991  @Override void add_val_work(Syntax child, Worklist work) { throw unimpl(); }
992  @Override boolean more_work(Worklist work) { return more_work_impl(work); }
993  @Override SB str(SB sb){ return sb.p(name()); }
994  @Override SB p1(SB sb) { return sb.p(name()); }
995  @Override SB p2(SB sb, VBitSet dups){ return sb; }
996  }
997 
998 
999  // Curried Pair
1000  static class Pair1 extends PrimSyn {
1001  @Override String name() { return "pair1"; }
1002  static private T2 var1,var2;
1003  static HashMap<Type,Pair1X> PAIR1S = new HashMap<>();
1004  public Pair1() {
1005  super(var1=T2.make_leaf(),T2.make_fun(BitsFun.ANY,var2=T2.make_leaf(),T2.make_struct(BitsAlias.make0(PAIR_ALIAS),new String[]{"0","1"},new T2[]{var1,var2})));
1006  }
1007  @Override PrimSyn make() { return new Pair1(); }
1008  @Override Type apply(Syntax[] args) {
1009  Type t = args[0]._flow;
1010  Pair1X p1x = PAIR1S.get(t);
1011  if( p1x == null )
1012  PAIR1S.put(t,p1x = new Pair1X(t));
1013  return p1x._flow;
1014  }
1015  static class Pair1X extends PrimSyn {
1016  final Type _con;
1017  @Override String name() { return "Pair1_"+_con; }
1018  static private T2 var2;
1019  public Pair1X(Type con) {
1020  super(var2=T2.make_leaf(),T2.make_struct(BitsAlias.make0(PAIR_ALIAS),new String[]{"0","1"},new T2[]{T2.make_base(con),var2}));
1021  _con=con;
1022  }
1023  @Override PrimSyn make() { throw unimpl(); }
1024  //@Override boolean hm(Worklist work) { throw unimpl(); }
1025  @Override Type apply(Syntax[] args) {
1026  T2 tcon = find().args(1).args(0);
1027  assert tcon.is_base();
1028  return TypeMemPtr.make(PAIR_ALIAS,TypeStruct.make(TypeStruct.tups(tcon._flow,args.length==0 ? Root.widen(_targs[0]) : args[0]._flow)));
1029  }
1030  }
1031  }
1032 
1033  // Pair
1034  static class Pair extends PrimSyn {
1035  @Override String name() { return "pair"; }
1036  static private T2 var1,var2;
1037  public Pair() {
1038  super(var1=T2.make_leaf(),var2=T2.make_leaf(),T2.make_struct(BitsAlias.make0(PAIR_ALIAS),new String[]{"0","1"},new T2[]{var1,var2}));
1039  }
1040  @Override PrimSyn make() { return new Pair(); }
1041  @Override Type apply(Syntax[] args) {
1042  TypeFld[] ts = TypeFlds.get(args.length+1);
1043  ts[0] = TypeFld.NO_DISP; // Display
1044  for( int i=0; i<args.length; i++ ) ts[i+1] = TypeFld.make_tup(args[i]._flow,i+1);
1046  }
1047  }
1048 
1049 
1050  // Triple
1051  static class Triple extends PrimSyn {
1052  @Override String name() { return "triple"; }
1053  static private T2 var1,var2,var3;
1054  public Triple() { super(var1=T2.make_leaf(),var2=T2.make_leaf(),var3=T2.make_leaf(),T2.make_struct(BitsAlias.make0(TRIPLE_ALIAS),new String[]{"0","1","2"},new T2[]{var1,var2,var3})); }
1055  @Override PrimSyn make() { return new Triple(); }
1056  @Override Type apply(Syntax[] args) {
1057  TypeFld[] ts = TypeFlds.get(args.length+1);
1058  ts[0] = TypeFld.NO_DISP; // Display
1059  for( int i=0; i<args.length; i++ ) ts[i+1] = TypeFld.make_tup(args[i]._flow,i+1);
1061  }
1062  }
1063 
1064  // Special form of a Lambda body for IF which changes the H-M rules.
1065  // None-executing paths do not unify args.
1066  static class If extends PrimSyn {
1067  @Override String name() { return "if"; }
1068  public If() { super(T2.make_leaf(),T2.make_leaf(),T2.make_leaf(),T2.make_leaf()); }
1069  @Override PrimSyn make() { return new If(); }
1070  @Override boolean hm(Worklist work) {
1071  T2 rez = find().args(3);
1072  // GCP helps HM: do not unify dead control paths
1073  if( DO_GCP ) { // Doing GCP during HM
1074  Type pred = _types[0];
1075  if( pred == TypeInt.FALSE || pred == Type.NIL || pred==Type.XNIL )
1076  return rez.unify(targ(2),work); // Unify only the false side
1077  if( pred.above_center() ) // Neither side executes
1078  return false; // Unify neither side
1079  if( !pred.must_nil() ) // Unify only the true side
1080  return rez.unify(targ(1),work);
1081  }
1082  // Unify both sides with the result
1083  return
1084  rez.unify(targ(1),work) |
1085  rez.find().unify(targ(2),work);
1086  }
1087  @Override Type apply( Syntax[] args) {
1088  Type pred= args[0]._flow;
1089  Type t1 = args[1]._flow;
1090  Type t2 = args[2]._flow;
1091  // Conditional Constant Propagation: only prop types from executable sides
1092  if( pred == TypeInt.FALSE || pred == Type.NIL || pred==Type.XNIL )
1093  return t2; // False only
1094  if( pred.above_center() ) // Delay any values
1095  return Type.XSCALAR; // t1.join(t2); // Join of either
1096  if( !pred.must_nil() ) // True only
1097  return t1;
1098  // Could be either, so meet
1099  return t1.meet(t2);
1100  }
1101  }
1102 
1103  // EQ
1104  static class EQ extends PrimSyn {
1105  @Override String name() { return "eq"; }
1106  static private T2 var1;
1107  public EQ() { super(var1=T2.make_leaf(),var1,BOOL); }
1108  @Override PrimSyn make() { return new EQ(); }
1109  @Override Type apply( Syntax[] args) {
1110  Type x0 = args[0]._flow;
1111  Type x1 = args[1]._flow;
1112  if( x0.above_center() || x1.above_center() ) return TypeInt.BOOL.dual();
1113  if( x0.is_con() && x1.is_con() && x0==x1 )
1114  return TypeInt.TRUE;
1115  // TODO: Can also know about nil/not-nil
1116  return TypeInt.BOOL;
1117  }
1118  }
1119 
1120  // EQ0
1121  static class EQ0 extends PrimSyn {
1122  @Override String name() { return "eq0"; }
1123  public EQ0() { super(INT64,BOOL); }
1124  @Override PrimSyn make() { return new EQ0(); }
1125  @Override Type apply( Syntax[] args) {
1126  Type pred = args[0]._flow;
1127  if( pred.above_center() ) return TypeInt.BOOL.dual();
1128  if( pred==Type.ALL ) return TypeInt.BOOL;
1129  if( pred == TypeInt.FALSE || pred == Type.NIL || pred==Type.XNIL )
1130  return TypeInt.TRUE;
1131  if( pred.meet_nil(Type.NIL)!=pred )
1132  return TypeInt.FALSE;
1133  return TypeInt.BOOL;
1134  }
1135  }
1136 
1137  static class IsEmpty extends PrimSyn {
1138  @Override String name() { return "isempty"; }
1139  public IsEmpty() { super(STRP,BOOL); }
1140  @Override PrimSyn make() { return new IsEmpty(); }
1141  @Override Type apply( Syntax[] args) {
1142  Type pred = args[0]._flow;
1143  if( pred.above_center() ) return TypeInt.BOOL.dual();
1144  TypeObj to;
1145  if( pred instanceof TypeMemPtr && (to=((TypeMemPtr)pred)._obj) instanceof TypeStr && to.is_con() )
1146  return TypeInt.con(to.getstr().isEmpty() ? 1 : 0);
1147  return TypeInt.BOOL;
1148  }
1149  }
1150 
1151  // Remove a nil from a struct after a guarding if-test
1152  static class NotNil extends PrimSyn {
1153  @Override String name() { return " notnil"; }
1154  public NotNil() { super(T2.make_leaf(),T2.make_leaf()); }
1155  @Override PrimSyn make() { return new NotNil(); }
1156  @Override int prep_tree( Syntax par, VStack nongen, Worklist work ) {
1157  int cnt = super.prep_tree(par,nongen,work);
1158  find().args(1).push_update(this);
1159  return cnt;
1160  }
1161  @Override boolean hm(Worklist work) {
1162  T2 arg = targ(0);
1163  if( arg.is_err() ) return false; // Already an error
1164  T2 fun = find(); assert fun.is_fun();
1165  T2 ret = fun.args(1);
1166  // If the arg is already nilchecked, can be a nilable of a nilable.
1167  if( arg==ret ) return false;
1168  // Already an expanded nilable
1169  if( arg.is_nilable() && arg.args(0) == ret ) return false;
1170  // Already an expanded nilable with base
1171  if( arg.is_base() && ret.is_base() ) {
1172  if( arg._flow == ret._flow.meet_nil(Type.XNIL) ) return false;
1173  if( work==null ) return true;
1174  Type mt = arg._flow.meet(ret._flow);
1175  Type rflow = mt.join(Type.NSCALR);
1176  Type aflow = mt.meet_nil(Type.XNIL);
1177  if( rflow != ret._flow ) { ret._flow=rflow; work.push(_par); }
1178  if( aflow != arg._flow ) { arg._flow=aflow; work.push(_par); }
1179  return true;
1180  }
1181  // Already an expanded nilable with struct
1182  if( arg.is_struct() && ret.is_struct() && arg._alias == arg._alias.meet_nil() && arg._ids.length == ret._ids.length ) {
1183  // But cannot just check the aliases, since they may not match.
1184  // Also check that the fields align
1185  boolean progress=false;
1186  for( int i=0; i<arg._ids.length; i++ )
1187  if( !Util.eq(arg._ids[i],ret._ids[i]) ||
1188  arg.args(i)!=ret.args(i) )
1189  { progress=true; break; } // Field/HMtypes misalign
1190  if( !progress ) return false; // No progress
1191  }
1192  if( work==null ) return true;
1193  // If the arg is already nilchecked, can be a nilable of a nilable.
1194  if( arg.is_nilable() && ret.is_nilable() )
1195  return arg.unify(ret,work);
1196  // Unify with arg with a nilable version of the ret.
1197  return T2.make_nil(ret).find().unify(arg,work);
1198  }
1199  @Override Type apply( Syntax[] args) {
1200  Type val = args[0]._flow;
1201  if( val==Type.XNIL ) return Type.XSCALAR; // Weird case of not-nil nil
1202  return val.join(Type.NSCALR);
1203  }
1204  }
1205 
1206  // multiply
1207  static class Mul extends PrimSyn {
1208  @Override String name() { return "*"; }
1209  public Mul() { super(INT64,INT64,INT64); }
1210  @Override PrimSyn make() { return new Mul(); }
1211  @Override Type apply( Syntax[] args) {
1212  Type t0 = args[0]._flow;
1213  Type t1 = args[1]._flow;
1214  if( t0.above_center() || t1.above_center() )
1215  return TypeInt.INT64.dual();
1216  if( t0 instanceof TypeInt && t1 instanceof TypeInt ) {
1217  if( t0.is_con() && t0.getl()==0 ) return TypeInt.ZERO;
1218  if( t1.is_con() && t1.getl()==0 ) return TypeInt.ZERO;
1219  if( t0.is_con() && t1.is_con() )
1220  return TypeInt.con(t0.getl()*t1.getl());
1221  }
1222  return TypeInt.INT64;
1223  }
1224  }
1225 
1226  // add integers
1227  static class Add extends PrimSyn {
1228  @Override String name() { return "+"; }
1229  public Add() { super(INT64,INT64,INT64); }
1230  @Override PrimSyn make() { return new Add(); }
1231  @Override Type apply( Syntax[] args) {
1232  Type t0 = args[0]._flow;
1233  Type t1 = args[1]._flow;
1234  if( t0.above_center() || t1.above_center() )
1235  return TypeInt.INT64.dual();
1236  if( t0 instanceof TypeInt && t1 instanceof TypeInt ) {
1237  if( t0.is_con() && t1.is_con() )
1238  return TypeInt.con(t0.getl()+t1.getl());
1239  }
1240  return TypeInt.INT64;
1241  }
1242  }
1243 
1244  // decrement
1245  static class Dec extends PrimSyn {
1246  @Override String name() { return "dec"; }
1247  public Dec() { super(INT64,INT64); }
1248  @Override PrimSyn make() { return new Dec(); }
1249  @Override Type apply( Syntax[] args) {
1250  Type t0 = args[0]._flow;
1251  if( t0.above_center() ) return TypeInt.INT64.dual();
1252  if( t0 instanceof TypeInt && t0.is_con() )
1253  return TypeInt.con(t0.getl()-1);
1254  return TypeInt.INT64;
1255  }
1256  }
1257 
1258  // int->str
1259  static class Str extends PrimSyn {
1260  @Override String name() { return "str"; }
1261  public Str() { super(INT64,STRP); }
1262  @Override PrimSyn make() { return new Str(); }
1263  @Override Type apply( Syntax[] args) {
1264  Type i = args[0]._flow;
1265  if( i.above_center() ) return TypeMemPtr.STRPTR.dual();
1266  if( i instanceof TypeInt && i.is_con() )
1267  return TypeMemPtr.make(BitsAlias.STRBITS,TypeStr.con(String.valueOf(i.getl()).intern()));
1268  return TypeMemPtr.STRPTR;
1269  }
1270  }
1271 
1272 
1273  // flt->(factor flt flt)
1274  static class Factor extends PrimSyn {
1275  @Override String name() { return "factor"; }
1276  public Factor() { super(FLT64,FLT64); }
1277  @Override PrimSyn make() { return new Factor(); }
1278  @Override Type apply( Syntax[] args) {
1279  Type flt = args[0]._flow;
1280  if( flt.above_center() ) return TypeFlt.FLT64.dual();
1281  return TypeFlt.FLT64;
1282  }
1283  }
1284 
1285  // ---------------------------------------------------------------------
1286  // T2 types form a Lattice, with 'unify' same as 'meet'. T2's form a DAG
1287  // (cycles if i allow recursive unification) with sharing. Each Syntax has a
1288  // T2, and the forest of T2s can share. Leaves of a T2 can be either a
1289  // simple concrete base type, or a sharable leaf. Unify is structural, and
1290  // where not unifyable the union is replaced with an Error.
1291  static class T2 implements Cloneable {
1292  private static int CNT=0;
1293  final int _uid;
1294 
1295  // A plain type variable starts with a 'V', and can unify directly.
1296  // Everything else is structural - during unification they must match names
1297  // and arguments and Type constants.
1298  @NotNull String _name; // name, e.g. "->" or "pair" or "V123" or "base"
1299 
1300  // Structural parts to unify with, or slot 0 is used during normal U-F
1302 
1303  // A dataflow type. Unused for everything except base type-vars (i.e.
1304  // constants, primitive tvars). Splitting these to make it easier to tease
1305  // apart when they should be used, and when not. Root needs a way to
1306  // recursively make a flow type from an HM type and the confusion is that
1307  // the _flow field is a valid flow type... it is not except and only for
1308  // Base types.
1310  BitsFun _fidxs; // Unused except for is_fun
1311  // Structs have field names and aliases
1312  BitsAlias _alias; // Unused except for is_struct and NIL
1313  String[] _ids;
1314  boolean _open; // Struct can be extended
1315  String _err; // Error
1316 
1317  // Dependent (non-local) tvars to revisit
1319 
1320  // Constructor factories.
1321  static T2 make_leaf() { return new T2("V"+CNT); }
1322  static T2 make_nil(T2 leaf) { return new T2("?",leaf); }
1323  static T2 make_base(Type flow) { T2 base = new T2("Base"); base._flow = flow; return base; }
1324  static T2 make_fun(BitsFun fidxs, T2... args) { T2 tfun = new T2("->",args); tfun._fidxs = fidxs; return tfun; }
1325  static T2 make_struct( BitsAlias aliases, String[] ids, T2[] flds ) { return make_struct(aliases,ids,flds,false); }
1326  static T2 make_struct( BitsAlias aliases, String[] ids, T2[] flds, boolean open ) {
1327  T2 tstr = new T2("@{}",flds);
1328  tstr._alias=aliases;
1329  tstr._ids = ids;
1330  tstr._open= open;
1331  return tstr;
1332  }
1333  static T2 make_err(String s) { T2 terr = new T2("Err"); terr._err = s.intern(); return terr; }
1334  T2 miss_field(String id) { return make_err("Missing field "+id+" in "+p()); }
1335  T2 copy() {
1336  T2 t = new T2(_name);
1337  if( _args!=null ) t._args = new T2[_args.length];
1338  t._flow = _flow;
1339  t._fidxs = _fidxs;
1340  t._alias = _alias;
1341  t._ids = _ids;
1342  t._err = _err;
1343  t._deps = _deps;
1344  t._open = _open;
1345  return t;
1346  }
1347 
1348  private T2(@NotNull String name) { _uid = CNT++; _name= name; }
1349  private T2(@NotNull String name, T2 @NotNull ... args) {
1350  this(name);
1351  _args= args;
1352  }
1353 
1354  // A type var, not a concrete leaf. Might be U-Fd or not.
1355  boolean is_leaf() { return _name.charAt(0)=='V' || _name.charAt(0)=='X'; }
1356  boolean no_uf() { return _name.charAt(0)!='X' && (!is_nilable() || _args[0].is_leaf()); }
1357  boolean isa(String name) { return Util.eq(_name,name); }
1358  boolean is_base() { return isa("Base"); }
1359  boolean is_nilable() { return isa("?"); }
1360  boolean is_fun () { return isa("->"); }
1361  boolean is_struct() { return isa("@{}"); }
1362  boolean is_err() { return isa("Err"); }
1363 
1364  T2 debug_find() {// Find, without the roll-up
1365  if( !is_leaf() ) return this; // Shortcut
1366  if( _args==null ) return this;
1367  T2 u = _args[0];
1368  if( u.no_uf() ) return u; // Shortcut
1369  // U-F search, no fixup
1370  while( u.is_leaf() && !u.no_uf() ) u = u._args[0];
1371  return u;
1372  }
1373 
1374  T2 find() {
1375  T2 u = _find0();
1376  return u.is_nilable() ? u._find_nil() : u;
1377  }
1378  // U-F find
1379  private T2 _find0() {
1380  T2 u = debug_find();
1381  if( u==this || u==_args[0] ) return u;
1382  T2 v = this, v2;
1383  // UF fixup
1384  while( v.is_leaf() && (v2=v._args[0])!=u ) { v._args[0]=u; v = v2; }
1385  return u;
1386  }
1387  // Nilable fixup. nil-of-leaf is OK. nil-of-anything-else folds into a
1388  // nilable version of the anything-else.
1389  private T2 _find_nil() {
1390  T2 n = args(0);
1391  if( n.is_leaf() ) return this;
1392  // Nested nilable-and-not-leaf, need to fixup the nilable
1393  if( n.is_base() ) {
1394  _flow = n._flow .meet_nil(Type.XNIL);
1395  _args = null;
1396  _name = n._name;
1397  } else if( n.is_struct() ) {
1398  _alias= n._alias.meet_nil();
1399  _args = n._args.clone();
1400  _ids = n._ids.clone();
1401  _open = n._open;
1402  _name = n._name;
1403  } else if( n.is_nilable() ) {
1404  _args[0] = n.args(0);
1405  } else
1406  throw unimpl();
1407 
1408  if( n._deps!=null ) {
1409  if( _deps == null ) _deps = n._deps;
1410  else _deps.addAll(n._deps);
1411  }
1412  return this;
1413  }
1414  // U-F find on the args array
1415  T2 args(int i) {
1416  T2 u = _args[i];
1417  T2 uu = u.find();
1418  return u==uu ? uu : (_args[i]=uu);
1419  }
1420 
1421  // Recursively build a conservative flow type from an HM type. The HM
1422  // is_struct wants to be a TypeMemPtr, but the recursive builder is built
1423  // around TypeStruct.
1424 
1425  // No function arguments, just function returns.
1428  assert ADUPS.isEmpty();
1429  Type t = _as_flow();
1430  ADUPS.clear();
1431  assert Type.intern_check();
1432  return t;
1433  }
1435  assert no_uf();
1436  if( is_base() ) return _flow;
1437  if( is_leaf() ) return Type.SCALAR;
1439  if( is_fun() ) return TypeFunPtr.make(_fidxs,_args.length-1,Type.ANY);
1440  if( is_nilable() ) return Type.SCALAR;
1441  if( is_struct() ) {
1442  TypeStruct tstr = ADUPS.get(_uid);
1443  if( tstr==null ) {
1444  Type.RECURSIVE_MEET++;
1445  TypeFld[] ts = TypeFlds.get(_ids.length+1);
1446  ts[0] = TypeFld.NO_DISP;
1447  for( int i=0; i<_ids.length; i++ )
1448  ts[i+1] = TypeFld.malloc(_ids[i],null,Access.Final,i+1);
1449  tstr = TypeStruct.malloc("",false,ts,true);
1450  tstr._hash = tstr.compute_hash();
1451  ADUPS.put(_uid,tstr); // Stop cycles
1452  for( int i=0; i<_ids.length; i++ )
1453  ts[i+1].setX(args(i)._as_flow()); // Recursive
1454  if( --Type.RECURSIVE_MEET == 0 ) {
1455  // Shrink / remove cycle dups. Might make new (smaller)
1456  // TypeStructs, so keep RECURSIVE_MEET enabled.
1457  Type.RECURSIVE_MEET++;
1458  tstr = TypeStruct.shrink(tstr.reachable(),tstr);
1459  TypeStruct.UF.clear();
1460  Type.RECURSIVE_MEET--;
1461  // Walk the final cyclic structure and intern everything.
1462  tstr.install_cyclic(tstr.reachable());
1463  }
1464  } else {
1465  tstr._cyclic=true; // Been there, done that, just mark it cyclic
1466  }
1467  return TypeMemPtr.make(_alias,tstr);
1468  }
1469 
1470  throw unimpl();
1471  }
1472 
1473 
1474  // If LHS is null, return RHS (and no progress)
1475  // If RHS is null, return LHS (and progress)
1476  // Else return meet (and progress is LHS!=RHS)
1477  private Type meet_flow(T2 that) {
1478  if( this._flow==null ) return that._flow;
1479  if( that._flow==null ) return this._flow;
1480  return _flow.meet(that._flow);
1481  }
1482  private BitsFun meet_fidxs(T2 that) {
1483  if( this._fidxs==null ) return that._fidxs;
1484  if( that._fidxs==null ) return this._fidxs;
1485  return _fidxs.meet(that._fidxs);
1486  }
1487  private BitsAlias meet_alias(T2 that) {
1488  if( this._alias==null ) return that._alias;
1489  if( that._alias==null ) return this._alias;
1490  return _alias.meet(that._alias);
1491  }
1492  private String[] meet_ids(T2 that) {
1493  String[] ids = that._ids;
1494  if( _ids==ids ) return ids;
1495  if( _ids==null ) return ids;
1496  if( ids==null ) return _ids;
1497  if( _ids.length!=ids.length ) throw unimpl(); // Handled at a higher level
1498  for( String id : ids )
1499  if( Util.find(_ids, id) == -1 )
1500  throw unimpl();
1501  return ids; // Return RHS
1502  }
1503  private boolean meet_opens(T2 that) {
1504  if( _open==that._open ) return that._open;
1505  if( !is_struct() ) return that._open;
1506  if( !that.is_struct() ) return _open;
1507  throw unimpl();
1508  }
1509  private String meet_err(T2 that) {
1510  if( this._err==null ) return that._err;
1511  if( that._err==null ) return this._err;
1512  // TODO: Probably gather unrelated strings in a set
1513  return _uid < that._uid ? _err : that._err;
1514  }
1515  private int base_states() {
1516  int cnt=0;
1517  if( _flow !=null ) cnt++;
1518  if( _fidxs!=null ) cnt++;
1519  if( _err !=null ) cnt++;
1520  if( _alias!=null ) { cnt++; assert _ids!=null; }
1521  else assert _ids==null;
1522  return cnt;
1523  }
1524 
1525  // U-F union; this becomes that; returns 'that'.
1526  // No change if only testing, and reports progress.
1527  boolean union(T2 that, Worklist work) {
1528  assert no_uf() && that.no_uf(); // Cannot union twice
1529  assert base_states()<=1 && that.base_states()<=1;
1530  if( this==that ) return false;
1531  if( work==null ) return true; // Report progress without changing
1532  // Keep the merge of all base types, revisiting deps if any changes
1533  if( _flow !=that._flow ||
1534  _fidxs!=that._fidxs ||
1535  _alias!=that._alias ||
1536  _ids !=that._ids ||
1537  _open !=that._open ||
1538  !Util.eq(_err,that._err) )
1539  work.addAll(that._deps); // Any progress, revisit deps
1540  // If flow types are not compatible, return an error now
1541  if( _flow!=null & that._flow!=null && (_flow.widen() != that._flow.widen() && !_flow.isa(that._flow.widen())) )
1542  return union_err(that,work,"Cannot unify "+this.p()+" and "+that.p());
1543  that._flow = meet_flow (that);
1544  that._fidxs = meet_fidxs(that);
1545  that._alias = meet_alias(that);
1546  that._ids = meet_ids (that);
1547  that._open = meet_opens(that);
1548  that._err = meet_err (that);
1549  assert that._flow != Type.XNIL;
1550  if( that._err!=null ) { // Kill the base types in an error
1551  that._flow=null; that._fidxs=null; that._alias=null; that._ids=null;
1552  }
1553  // Hard union this into that, no more testing.
1554  return _union(that,work);
1555  }
1556 
1557  // U-F union; this is nilable and becomes that.
1558  // No change if only testing, and reports progress.
1559  boolean unify_nil(T2 that, Worklist work) {
1560  assert is_nilable() && !that.is_nilable();
1561  if( work==null ) return true; // Will make progress
1562  // Clone the top-level struct and make this nilable point to the clone;
1563  // this will collapse into the clone at the next find() call.
1564  // Unify the nilable leaf into that.
1565  T2 leaf = args(0); assert leaf.is_leaf();
1566  T2 copy = that.copy();
1567  if( that.is_base() ) {
1569  } else if( that.is_struct() ) {
1570  copy._alias = copy._alias.clear(0);
1571  System.arraycopy(that._args,0,copy._args,0,that._args.length);
1572  } else
1573  throw unimpl();
1574  return leaf._union(copy,work) | that._union(find(),work);
1575  }
1576 
1577  // Hard unify this into that, no testing for progress.
1578  private boolean _union(T2 that, Worklist work) {
1579  assert that.no_uf();
1580  _flow=null; _fidxs=null; _alias=null; _ids=null; _err=null; // Kill the base types in a unified type
1581  // Worklist: put updates on the worklist for revisiting
1582  if( _deps != null ) {
1583  work.addAll(_deps); // Re-Apply
1584  // Merge update lists, for future unions
1585  if( that._deps==null && that._args==null ) that._deps = _deps;
1586  else for( Syntax dep : _deps ) that.push_update(dep);
1587  _deps = null;
1588  }
1589  if( _args==null || _args.length!=1 ) _args = new T2[1];
1590  // Unify the two base types, preserving errors
1591  _args[0] = that; // U-F update
1592  _name = "X"+_uid; // Flag as a leaf & unified
1593  assert !no_uf();
1594  return true;
1595  }
1596 
1597  // -----------------
1598  // Structural unification.
1599  // Returns false if no-change, true for change.
1600  // If work is null, does not actually change anything, just reports progress.
1601  // If work and change, unifies 'this' into 'that' (changing both), and
1602  // updates the worklist.
1603  static private final HashMap<Long,T2> DUPS = new HashMap<>();
1604  boolean unify( T2 that, Worklist work ) {
1605  if( this==that ) return false;
1606  assert DUPS.isEmpty();
1607  boolean progress = _unify(that,work);
1608  DUPS.clear();
1609  return progress;
1610  }
1611 
1612  // Structural unification, 'this' into 'that'. No change if just testing
1613  // (work is null) and returns a progress flag. If updating, both 'this'
1614  // and 'that' are the same afterwards.
1615  private boolean _unify(T2 that, Worklist work) {
1616  assert no_uf() && that.no_uf();
1617  if( this==that ) return false;
1618 
1619  // All leaf types immediately unify.
1620  if( this._args==null && that._args==null ) {
1621  T2 lhs=this, rhs=that;
1622  if( is_err() || // Errors beat all others
1623  (!that.is_err() && is_base()) )
1624  { rhs=this; lhs=that; } // Base beats plain leaf
1625  // If tied, keep lower uid
1626  if( Util.eq(lhs._name,rhs._name) && _uid<that._uid ) { rhs=this; lhs=that; }
1627  return lhs.union(rhs,work);
1628  }
1629  // Any leaf immediately unifies with any non-leaf
1630  if( this.is_leaf() || that.is_err() ) return this.union(that,work);
1631  if( that.is_leaf() || this.is_err() ) return that.union(this,work);
1632  // Special case for nilable union something
1633  if( this.is_nilable() && !that.is_nilable() ) return this.unify_nil(that,work);
1634  if( that.is_nilable() && !this.is_nilable() ) return that.unify_nil(this,work);
1635 
1636  // Cycle check
1637  long luid = dbl_uid(that); // long-unique-id formed from this and that
1638  T2 rez = DUPS.get(luid);
1639  assert rez==null || rez==that;
1640  if( rez!=null ) return false; // Been there, done that
1641  DUPS.put(luid,that); // Close cycles
1642 
1643  if( work==null ) return true; // Here we definitely make progress; bail out early if just testing
1644 
1645  if( !Util.eq(_name,that._name) )
1646  return union_err(that,work,"Cannot unify "+this.p()+" and "+that.p());
1647  assert _args!=that._args; // Not expecting to share _args and not 'this'
1648 
1649  // Structural recursion unification.
1650 
1651  // Structs unify only on matching fields, and add missing fields.
1652  if( is_struct() ) {
1653  _unify_struct(that,work);
1654  that = that.find();
1655  } else { // Normal structural unification
1656  for( int i=0; i<_args.length; i++ ) { // For all fields in LHS
1657  args(i)._unify(that.args(i),work);
1658  if( (that=that.find()).is_err() ) break;
1659  }
1660  }
1661  if( find().is_err() && !that.is_err() )
1662  // TODO: Find a more elegant way to preserve errors
1663  return that.union(find(),work); // Preserve errors
1664  return find().union(that,work);
1665  }
1666 
1667  private void _unify_struct(T2 that, Worklist work) {
1668  assert this.is_struct() && that.is_struct();
1669  T2 thsi = this;
1670  // Unification for structs is more complicated; args are aligned via
1671  // field names and not by position. Conceptually, fields in one struct
1672  // and not the other are put in both before unifying the structs. Open
1673  // structs copy from the other side; closed structs insert a missing
1674  // field error.
1675  for( int i=0; i<thsi._ids.length; i++ ) { // For all fields in LHS
1676  int idx = Util.find(that._ids,thsi._ids[i]);
1677  if( idx==-1 ) // Missing that field? Copy from left if open, error if closed.
1678  that.add_fld(thsi._ids[i], that._open ? thsi.args(i) : that.miss_field(thsi._ids[i]), work);
1679  else thsi.args(i)._unify(that.args(idx),work); // Unify matching field
1680  if( (that=that.find()).is_err() ) return; // Recursively, might have already rolled this up
1681  thsi = thsi.find(); assert thsi.is_struct();
1682  }
1683  // Fields in RHS and not the LHS are also merged; if the LHS is open we'd
1684  // just copy the missing fields into it, then unify the structs
1685  // (shortcut: just skip the copy). If the LHS is closed, then the extra
1686  // RHS fields are an error.
1687  if( !thsi._open ) // LHS is closed, so extras in RHS are errors
1688  for( int i=0; i<that._ids.length; i++ ) // For all fields in RHS
1689  if( Util.find(thsi._ids,that._ids[i]) == -1 ) // Missing in LHS
1690  that.args(i)._unify(miss_field(that._ids[i]),work); // If closed, extra field is an error
1691  // Shortcut (for asserts): LHS gets same ids as RHS, since its about to be top-level unified
1692  thsi._ids = that._ids;
1693  thsi._open= that._open;
1694  }
1695 
1696  // Insert a new field; keep fields sorted
1697  private boolean add_fld(String id, T2 fld, Worklist work) {
1698  assert is_struct();
1699  int len = _ids.length;
1700  // Find insertion point
1701  int idx = Arrays.binarySearch(_ids,id);
1702  assert idx<0; // Never found
1703  idx = -idx-1; // Insertion point
1704  // Insert in sorted order
1705  _ids = Arrays.copyOf( _ids,len+1);
1706  _args = Arrays.copyOf(_args,len+1);
1707  System.arraycopy( _ids,idx, _ids,idx+1,len-idx);
1708  System.arraycopy(_args,idx,_args,idx+1,len-idx);
1709  _ids [idx] = id ;
1710  _args[idx] = fld;
1711  fld.push_update(_deps); // If field changes, all deps change
1712  work.addAll(_deps); //
1713  return true; // Always progress
1714  }
1715 
1716  private long dbl_uid(T2 t) { return dbl_uid(t._uid); }
1717  private long dbl_uid(long uid) { return ((long)_uid<<32)|uid; }
1718 
1719  private boolean fresh_base(T2 that, Worklist work) {
1720  assert base_states()<=1 && that.base_states()<=1;
1721  boolean progress=false;
1722  Type flow = meet_flow (that); progress |= flow != that._flow ;
1723  BitsFun fidxs = meet_fidxs(that); progress |= fidxs != that._fidxs;
1724  BitsAlias alias = meet_alias(that); progress |= alias != that._alias;
1725  String[] ids = meet_ids (that); progress |= ids != that._ids;
1726  boolean open = meet_opens(that); progress |= open != that._open;
1727  String err = meet_err (that); progress |= !Util.eq(err,that._err);
1728  if( !progress ) return false;
1729  if( work==null ) return true;
1730  // Progress
1731  Type that_flow = that._flow;
1732  that._flow = flow ;
1733  that._fidxs = fidxs;
1734  that._alias = alias;
1735  that._ids = ids;
1736  that._open = open;
1737  that._err = err;
1738  if( !_can_be_HM_base(that,that_flow) ) {
1739  that._flow = that_flow; // Unwind for error message
1740  String msg = "Cannot unify "+this.p()+" and "+that.p();
1741  that._flow=null; that._fidxs=null; that._alias=null; that._ids=null; // Now kill the base types, since in-error
1742  return that.union(make_err(msg),work);
1743  }
1744  assert that.base_states()<=1;
1745  that.add_deps_work(work);
1746  if( that.is_leaf() ) that._name = _name; // That is a base/err now
1747  return true;
1748  }
1749  private boolean _can_be_HM_base(T2 that, Type that_flow) {
1750  if( that.base_states() > 1 ) return false;
1751  if( _flow==null || that_flow==null ) return true;
1752  Type wthisflow = _flow.widen();
1753  Type wthatflow = that_flow.widen();
1754  if( wthisflow==wthatflow ) return true;
1755  return wthisflow.isa(wthatflow);
1756  }
1757  private boolean union_err(T2 that, Worklist work, String msg) {
1758  that._flow=null; that._fidxs=null; that._alias=null; that._ids=null; // Now kill the base types, since in-error
1759  union(that,work);
1760  return that.union(make_err(msg),work);
1761  }
1762 
1763  // -----------------
1764  // Make a (lazy) fresh copy of 'this' and unify it with 'that'. This is
1765  // the same as calling 'fresh' then 'unify', without the clone of 'this'.
1766  // Returns progress.
1767  // If work is null, we are testing only and make no changes.
1768  static private final HashMap<T2,T2> VARS = new HashMap<>();
1769  boolean fresh_unify(T2 that, VStack nongen, Worklist work) {
1770  assert VARS.isEmpty() && DUPS.isEmpty();
1771  int old = CNT;
1772  boolean progress = _fresh_unify(that,nongen,work);
1773  VARS.clear(); DUPS.clear();
1774  if( work==null && old!=CNT && DEBUG_LEAKS )
1775  throw unimpl("busted, made T2s but just testing");
1776  return progress;
1777  }
1778 
1779  // Outer recursive version, wraps a VARS check around other work
1780  private boolean _fresh_unify(T2 that, VStack nongen, Worklist work) {
1781  assert no_uf() && that.no_uf();
1782  T2 prior = VARS.get(this);
1783  if( prior!=null ) // Been there, done that
1784  return prior.find()._unify(that,work); // Also 'prior' needs unification with 'that'
1785  if( cycle_equals(that) ) return vput(that,false);
1786 
1787  if( that.is_err() ) return vput(that,false); // That is an error, ignore 'this' and no progress
1788  if( this.is_err() ) return vput(that,_unify(that,work));
1789 
1790  // In the non-generative set, so do a hard unify, not a fresh-unify.
1791  if( nongen_in(nongen) ) return vput(that,_unify(that,work)); // Famous 'occurs-check', switch to normal unify
1792 
1793  // LHS is a leaf, base, or error
1794  if( this._args==null ) return vput(that,fresh_base(that,work));
1795  if( that.is_leaf() ) // RHS is a tvar; union with a deep copy of LHS
1796  return work==null || vput(that,that.union(_fresh(nongen),work));
1797 
1798  // Special handling for nilable
1799  if( this.is_nilable() && !that.is_nilable() ) {
1800  if( that.is_base() ) {
1801  Type mt = that._flow.meet_nil(Type.XNIL);
1802  if( mt==that._flow ) return false; // Nilable already
1803  if( work!=null ) that._flow = mt;
1804  return true;
1805  }
1806  if( that.is_struct() ) {
1807  if( that._alias.test(0) ) return false; // Nilable already
1808  throw unimpl();
1809  }
1810 
1811  throw unimpl();
1812  }
1813  // That is nilable and this is not
1814  if( that.is_nilable() && !this.is_nilable() ) {
1815  if( this.is_struct() ) {
1816  // fresh_unify a not-nil version of this with the not-nil version of that
1817  T2 copy = this;
1818  if( copy._alias.test(0) ) { // make a not=nil version of struct
1819  copy = this.copy();
1820  copy._alias = copy._alias.clear(0);
1821  System.arraycopy(this._args,0,copy._args,0,this._args.length);
1822  }
1823  boolean progress = copy._fresh_unify(that.args(0),nongen,work);
1824  return _alias.test(0) ? vput(that,progress) : progress;
1825  }
1826  throw unimpl();
1827  }
1828 
1829  if( !Util.eq(_name,that._name) ||
1830  (!is_struct() && _args.length != that._args.length) )
1831  return work == null || vput(that,that._unify(make_err("Cannot unify "+this.p()+" and "+that.p()),work));
1832 
1833  // Structural recursion unification, lazy on LHS
1834  vput(that,false); // Early set, to stop cycles
1835  boolean progress = false;
1836  if( is_struct() )
1837  progress = _fresh_unify_struct(that,nongen,work);
1838  else {
1839  for( int i=0; i<_args.length; i++ ) {
1840  progress |= args(i)._fresh_unify(that.args(i),nongen,work);
1841  if( progress && work==null ) return true;
1842  if( (that=that.find()).is_err() ) return true;
1843  }
1844  if( is_fun() ) {
1845  BitsFun fidxs = meet_fidxs(that);
1846  if( fidxs!=that._fidxs ) progress=true;
1847  if( progress && work==null ) return true;
1848  that._fidxs = fidxs;
1849  }
1850  }
1851  return progress;
1852  }
1853 
1854  // Unification with structs must honor field names.
1855  private boolean _fresh_unify_struct(T2 that, VStack nongen, Worklist work) {
1856  assert is_struct() && that.is_struct();
1857  boolean progress = false;
1858  // Unification for structs is more complicated; args are aligned via
1859  // field names and not by position. Conceptually, fields in one struct
1860  // and not the other are put in both before unifying the structs. Open
1861  // structs copy from the other side; closed structs insert a missing
1862  // field error.
1863  for( int i=0; i<_ids.length; i++ ) {
1864  int idx = Util.find(that._ids,_ids[i]);
1865  if( idx == -1 ) { // Missing field on RHS
1866  if( work==null ) return true; // Will definitely make progress
1867  progress = true;
1868  // if both are closed, error on RHS
1869  that.add_fld(_ids[i], that._open ? args(i)._fresh(nongen) : that.miss_field(_ids[i]), work);
1870  } else
1871  progress |= args(i)._fresh_unify(that.args(idx),nongen,work);
1872  if( (that=that.find()).is_err() ) return true;
1873  if( progress && work==null ) return true;
1874  }
1875  // Fields in RHS and not the LHS are also merged; if the LHS is open we'd
1876  // just copy the missing fields into it, then unify the structs
1877  // (shortcut: just skip the copy). If the LHS is closed, then the extra
1878  // RHS fields are an error.
1879  if( !_open )
1880  for( int i=0; i<that._ids.length; i++ ) // For all fields in RHS
1881  if( Util.find(_ids,that._ids[i]) == -1 &&// Missing in LHS
1882  !that.args(i).is_err() ) { // And not yet an error
1883  if( work == null ) return true; // Will definitely make progress
1884  progress |= that.args(i).unify(miss_field(that._ids[i]), work);
1885  }
1886 
1887  // Unify aliases
1888  BitsAlias alias = meet_alias(that);
1889  if( alias!=that._alias ) progress=true;
1890  if( progress && work==null ) return true;
1891  that._alias = alias;
1892  return progress;
1893  }
1894 
1895  private boolean vput(T2 that, boolean progress) { VARS.put(this,that); return progress; }
1896 
1897  // Return a fresh copy of 'this'
1898  T2 fresh() {
1899  assert VARS.isEmpty();
1900  T2 rez = _fresh(null);
1901  VARS.clear();
1902  return rez;
1903  }
1904  private T2 _fresh(VStack nongen) {
1905  assert no_uf();
1906  T2 rez = VARS.get(this);
1907  if( rez!=null ) return rez; // Been there, done that
1908  // Unlike the original algorithm, to handle cycles here we stop making a
1909  // copy if it appears at this level in the nongen set. Otherwise we'd
1910  // clone it down to the leaves - and keep all the nongen leaves.
1911  // Stopping here preserves the cyclic structure instead of unrolling it.
1912  if( nongen_in(nongen) ) {
1913  VARS.put(this,this);
1914  return this;
1915  }
1916 
1917  if( is_leaf() ) {
1918  // If occurs_in lexical scope, keep same variable, else make a new leaf
1919  T2 t = T2.make_leaf();
1920  VARS.put(this,t);
1921  return t;
1922  } else { // Structure is deep-replicated
1923  T2 t = copy();
1924  VARS.put(this,t); // Stop cyclic structure looping
1925  if( _args!=null )
1926  for( int i=0; i<_args.length; i++ )
1927  t._args[i] = args(i)._fresh(nongen);
1928  return t;
1929  }
1930  }
1931 
1932  // -----------------
1933  private static final VBitSet ODUPS = new VBitSet();
1934  boolean _occurs_in_type(T2 x) {
1935  assert no_uf() && x.no_uf();
1936  if( x==this ) return true;
1937  if( ODUPS.tset(x._uid) ) return false; // Been there, done that
1938  if( !x.is_leaf() && x._args!=null )
1939  for( int i=0; i<x._args.length; i++ )
1940  if( _occurs_in_type(x.args(i)) )
1941  return true;
1942  return false;
1943  }
1944 
1945  boolean occurs_in_type(T2 x) {
1946  ODUPS.clear();
1947  return _occurs_in_type(x);
1948  }
1949 
1950  boolean nongen_in(VStack vs) {
1951  if( vs==null ) return false;
1952  ODUPS.clear();
1953  for( T2 t2 : vs )
1954  if( _occurs_in_type(t2.find()) )
1955  return true;
1956  return false;
1957  }
1958 
1959  // -----------------
1960  // Test for structural equivalence, including cycles
1961  static private final HashMap<T2,T2> CDUPS = new HashMap<>();
1962  boolean cycle_equals(T2 t) {
1963  assert CDUPS.isEmpty();
1964  boolean rez = _cycle_equals(t);
1965  CDUPS.clear();
1966  return rez;
1967  }
1968  boolean _cycle_equals(T2 t) {
1969  assert no_uf() && t.no_uf();
1970  if( this==t ) return true;
1971  if( _flow !=t._flow || // Base-cases have to be completely identical
1972  _fidxs!=t._fidxs ||
1973  _alias!=t._alias ||
1974  !Util.eq(_err,t._err) )
1975  return false;
1976  if( !Util.eq(_name,t._name) ) return false; // Wrong type-var names
1977  if( _args==t._args ) return true; // Same arrays (generally both null)
1978  if( _args.length != t._args.length ) // Mismatched sizes
1979  return false;
1980  // Cycles stall the equal/unequal decision until we see a difference.
1981  T2 tc = CDUPS.get(this);
1982  if( tc!=null ) return tc==t; // Cycle check; true if both cycling the same
1983  CDUPS.put(this,t);
1984  if( is_struct() ) // Struct equality honors field names without regard to order
1985  return _cycle_equals_struct(t);
1986  for( int i=0; i<_args.length; i++ )
1987  if( !args(i)._cycle_equals(t.args(i)) )
1988  return false;
1989  return true;
1990  }
1991 
1992  private boolean _cycle_equals_struct(T2 t) {
1993  assert is_struct() && t.is_struct();
1994  for( int i=0; i<_args.length; i++ ) {
1995  int idx = Util.find(t._ids,_ids[i]);
1996  if( idx==-1 || !args(i)._cycle_equals(t.args(idx)) )
1997  return false;
1998  }
1999  return true;
2000  }
2001 
2002  // -----------------
2003  // Walk a T2 and a matching flow-type, and build a map from T2 to flow-types.
2004  // Stop if either side loses structure.
2006  long duid = dbl_uid(t._uid);
2007  if( Apply.WDUPS.putIfAbsent(duid,"")!=null ) return t;
2008  assert no_uf();
2009  if( is_err() ) return fput(t); //
2010  // Base variables (when widened to an HM type) might force a lift.
2011  if( is_base() ) return fput(_flow.widen().join(t));
2012  // Free variables keep the input flow type.
2013  if( is_leaf() ) return fput(t);
2014  // Nilable
2015  if( is_nilable() ) {
2016  fput(t);
2017  args(0).walk_types_in(t); // TODO: Not sure if i should strip nil or not
2018  return t;
2019  }
2020  if( t==Type.SCALAR || t==Type.NSCALR ) return fput(t); // Will be scalar for all the breakdown types
2021  if( is_fun() ) {
2022  if( !(t instanceof TypeFunPtr) ) return t; // Typically, some kind of error situation
2023  // TODO: PAIR1 should report better
2024  TypeFunPtr tfp = (TypeFunPtr)t;
2025  T2 ret = args(_args.length-1);
2026  if( tfp._fidxs==BitsFun.FULL ) return ret.walk_types_in(Type. SCALAR);
2027  if( tfp._fidxs==BitsFun.FULL.dual() ) return ret.walk_types_in(Type.XSCALAR);
2028  for( int fidx : ((TypeFunPtr)t)._fidxs ) {
2029  Lambda lambda = Lambda.FUNS.get(fidx);
2030  Type body = lambda.find().is_err()
2031  ? Type.SCALAR // Error, no lift
2032  : (lambda._body == null // Null only for primitives
2033  ? lambda.find().args(lambda._targs.length).as_flow() // Get primitive return type
2034  : lambda._body._flow); // Else use body type
2035  ret.walk_types_in(body);
2036  }
2037  return t;
2038  }
2039 
2040  if( is_struct() ) {
2041  fput(t); // Recursive types need to put themselves first
2042  if( !(t instanceof TypeMemPtr) ) return t;
2043  TypeMemPtr tmp = (TypeMemPtr)t;
2044  if( !(tmp._obj instanceof TypeStruct) ) return t;
2045  TypeStruct ts = (TypeStruct)tmp._obj;
2046  for( int i=0; i<_args.length; i++ ) {
2047  int idx = ts.fld_find(_ids[i]);
2048  // Missing fields are walked as SCALAR
2049  args(i).walk_types_in(idx==-1 ? Type.SCALAR : ts.at(idx));
2050  }
2051  return ts;
2052  }
2053 
2054  throw unimpl();
2055  }
2056  private Type fput(final Type t) {
2057  Apply.T2MAP.merge(this, t, Type::meet);
2058  return t;
2059  }
2060 
2062  assert no_uf();
2063  if( t == Type.XSCALAR ) return t; // No lift possible
2064  Type tmap = Apply.T2MAP.get(this);
2065  if( tmap != null ) return tmap;
2066  if( is_err() ) throw unimpl();
2067  assert !is_leaf() && !is_base(); // All output leafs found as inputs already
2068  if( is_fun() ) return t; // No change, already known as a function (and no TFS in the flow types)
2069  if( is_struct() ) {
2070  if( !(t instanceof TypeMemPtr) ) throw unimpl();
2071  TypeMemPtr tmp = (TypeMemPtr)t;
2072  if( !(tmp._obj instanceof TypeStruct) ) throw unimpl();
2073  TypeStruct ts = (TypeStruct)tmp._obj;
2074  boolean progress=false;
2075  for( int i=0; i<_args.length; i++ ) {
2076  int idx = ts.fld_find(_ids[i]);
2077  if( idx==-1 ) continue;
2078  Type targ = ts.at(idx);
2079  Type rez = args(i).walk_types_out(targ);
2080  progress |= targ != rez;
2081  }
2082  if( !progress ) return t;
2083  // Make a new result
2084  TypeFld[] flds = TypeFlds.get(ts.len());
2085  for( int i=0; i<_args.length; i++ ) {
2086  int idx = ts.fld_find(_ids[i]);
2087  if( idx==-1 ) continue;
2088  Type targ = ts.at(idx);
2089  Type rez = args(i).walk_types_out(targ);
2090  flds[i] = ts.fld(i).make_from(rez);
2091  }
2092  return tmp.make_from(ts.make_from(flds));
2093  }
2094  throw unimpl(); // Handled all cases
2095  }
2096 
2097  // -----------------
2098  private static final VBitSet FIDX_VISIT = new VBitSet();
2099  private static BitsFun FIDXS = null;
2101  private void _find_fidxs() {
2102  if( FIDX_VISIT.tset(_uid) ) return;
2103  if( is_struct() )
2104  for( T2 arg : _args )
2105  arg._find_fidxs();
2106  if( is_fun() ) {
2107  FIDXS = FIDXS.meet(_fidxs);
2108  args(_args.length-1)._find_fidxs();
2109  }
2110  }
2111 
2112  // -----------------
2113  // This is a T2 function that is the target of 'fresh', i.e., this function
2114  // might be fresh-unified with some other function. Push the application
2115  // down the function parts; if any changes the fresh-application may make
2116  // progress.
2117  static final VBitSet UPDATE_VISIT = new VBitSet();
2118  T2 push_update( Ary<Syntax> as ) { if( as != null ) for( Syntax a : as ) push_update(a); return this; }
2119  T2 push_update( Syntax a) { assert UPDATE_VISIT.isEmpty(); push_update_impl(a); UPDATE_VISIT.clear(); return this; }
2120  private void push_update_impl(Syntax a) {
2121  assert no_uf();
2122  if( UPDATE_VISIT.tset(_uid) ) return;
2123  if( _deps==null ) _deps = new Ary<>(Syntax.class);
2124  if( _deps.find(a)==-1 ) _deps.push(a);
2125  if( _args!=null )
2126  for( int i=0; i<_args.length; i++ )
2127  if( _args[i]!=null )
2128  args(i).push_update_impl(a);
2129  }
2130 
2131  // Recursively add-deps to worklist
2132  void add_deps_work( Worklist work ) { assert UPDATE_VISIT.isEmpty(); add_deps_work_impl(work); UPDATE_VISIT.clear(); }
2133  private void add_deps_work_impl( Worklist work ) {
2134  if( is_leaf() ) {
2135  work.addAll(_deps);
2136  } else {
2137  if( UPDATE_VISIT.tset(_uid) ) return;
2138  if( _args != null )
2139  for( int i=0; i<_args.length; i++ )
2140  args(i).add_deps_work_impl(work);
2141  }
2142  }
2143 
2144  // -----------------
2145  // Glorious Printing
2146 
2147  // Look for dups, in a tree or even a forest (which Syntax.p() does)
2148  VBitSet get_dups(VBitSet dups) { return _get_dups(new VBitSet(),dups); }
2150  if( visit.tset(_uid) ) {
2151  dups.set(debug_find()._uid);
2152  } else
2153  if( _args!=null )
2154  for( T2 t : _args )
2155  if( t!=null )
2156  t._get_dups(visit,dups);
2157  return dups;
2158  }
2159 
2160  // Fancy print for Debuggers - includes explicit U-F re-direction.
2161  // Does NOT roll-up U-F, has no side-effects.
2162  @Override public String toString() { return str(new SB(), new VBitSet(), get_dups(new VBitSet()) ).toString(); }
2163  SB str(SB sb, VBitSet visit, VBitSet dups) {
2164 
2165  if( is_err () ) return sb.p(_err);
2166  if( is_base() ) return sb.p(_flow);
2167  boolean dup = dups.get(_uid);
2168  if( is_leaf() ) {
2169  sb.p(_name);
2170  return no_uf() ? sb : _args[0].str(sb.p(">>"), visit, dups);
2171  }
2172  if( dup ) sb.p("$V").p(_uid);
2173  if( visit.tset(_uid) && dup ) return sb;
2174  if( dup ) sb.p(':');
2175 
2176  // Special printing for functions
2177  if( is_fun() ) {
2178  sb.p("{");
2179  if( _fidxs==null ) sb.p('_'); else _fidxs.str(sb);
2180  sb.p(' ');
2181  for( int i=0; i<_args.length-1; i++ )
2182  str(sb,visit,_args[i],dups).p(" ");
2183  return str(sb.p("-> "),visit,_args[_args.length-1],dups).p(" }");
2184  }
2185 
2186  // Special printing for structures
2187  if( is_struct() ) {
2188  sb.p("@{");
2189  if( _alias==null ) sb.p('_'); else _alias.str(sb);
2190  sb.p(' ');
2191  if( _ids==null ) sb.p("_ ");
2192  else for( int i=0; i<_ids.length; i++ )
2193  str(sb.p(' ').p(_ids[i]).p(" = "),visit,_args[i],dups).p(',');
2194  return sb.unchar().p("}");
2195  }
2196 
2197  // Generic structural T2
2198  sb.p("(").p(_name).p(" ");
2199  for( T2 t : _args ) str(sb,visit,t,dups).p(" ");
2200  return sb.unchar().p(")");
2201  }
2202  static private SB str(SB sb, VBitSet visit, T2 t, VBitSet dups) { return t==null ? sb.p("_") : t.str(sb,visit,dups); }
2203 
2204  // Same as toString but calls find(). Can thus side-effect & roll-up U-Fs, so not a toString
2205  public String p() { return p(get_dups(new VBitSet())); }
2206  private static int VCNT;
2207  private static final HashMap<T2,Integer> VNAMES = new HashMap<>();
2208  String p(VBitSet dups) { VCNT=0; VNAMES.clear(); return find()._p(new SB(), new VBitSet(), dups).toString(); }
2209  private SB _p(SB sb, VBitSet visit, VBitSet dups) {
2210  assert no_uf();
2211  if( is_base() ) return sb.p(_flow); // One-shot bases just do type
2212  if( is_leaf() || dups.get(_uid) ) { // Leafs or Duplicates? Take some effort to pretty-print cycles
2213  Integer ii = VNAMES.get(this);
2214  if( ii==null ) VNAMES.put(this,ii=VCNT++); // Type-var name
2215  // 2nd and later visits use the short form
2216  boolean later = visit.tset(_uid);
2217  // Removed as being more confusing to more academic readers
2218  //if( later ) sb.p('$');
2219  char c = (char)('A'+ii);
2220  if( c<'V' ) sb.p(c); else sb.p("V"+ii);
2221  if( later ) return sb;
2222  if( is_leaf() ) return sb;
2223  sb.p(':'); // Dups now print their structure
2224  }
2225  if( is_err () ) return sb.p(_err);
2226 
2227  // Special printing for functions: { arg -> body }
2228  if( is_fun() ) {
2229  sb.p("{ ");
2230  for( int i=0; i<_args.length-1; i++ )
2231  args(i)._p(sb,visit,dups).p(" ");
2232  return args(_args.length-1)._p(sb.p("-> "),visit,dups).p(" }");
2233  }
2234 
2235  // Special printing for structures: @{ fld0 = body, fld1 = body, ... }
2236  if( is_struct() ) {
2237  if( is_tuple() ) {
2238  if( _ids.length == 0 ) return sb.p("()");
2239  sb.p('(');
2240  for( int i=0; i<_ids.length; i++ ) {
2241  int idx = Util.find(_ids,new String(new char[]{(char)('0'+i)}).intern());
2242  args(idx)._p(sb.p(' '),visit,dups).p(',');
2243  }
2244  sb.unchar().p(')');
2245 
2246  } else {
2247  sb.p("@{");
2248  TreeMap<String,Integer> map = new TreeMap<>();
2249  for( int i=0; i<_ids.length; i++ )
2250  map.put( _ids[i], i );
2251  for( int i : map.values() )
2252  args(i)._p(sb.p(' ').p(_ids[i]).p(" = "),visit,dups).p(',');
2253  sb.unchar().p("}");
2254  }
2255  //return _alias.str(sb);
2256  if( _alias.test(0) ) sb.p('?');
2257  return sb;
2258  }
2259 
2260  if( is_nilable() )
2261  return args(0)._p(sb,visit,dups).p('?');
2262 
2263  // Generic structural T2: (fun arg0 arg1...)
2264  sb.p("(").p(_name).p(" ");
2265  for( int i=0; i<_args.length; i++ ) args(i)._p(sb,visit,dups).p(" ");
2266  return sb.unchar().p(")");
2267  }
2268 
2269  boolean is_tuple() {
2270  if( _ids==null ) return false;
2271  for( String id : _ids )
2272  if( !isDigit((byte) id.charAt(0)) )
2273  return false;
2274  return true;
2275  }
2276 
2277  // Debugging tool
2278  T2 find(int uid) { return _find(uid,new VBitSet()); }
2279  private T2 _find(int uid, VBitSet visit) {
2280  if( visit.tset(_uid) ) return null;
2281  if( _uid==uid ) return this;
2282  if( _args==null ) return null;
2283  for( T2 arg : _args )
2284  if( (arg=arg._find(uid,visit)) != null )
2285  return arg;
2286  return null;
2287  }
2288  static void reset() { CNT=0; DUPS.clear(); VARS.clear(); ODUPS.clear(); CDUPS.clear(); UPDATE_VISIT.clear(); }
2289  }
2290 
2291 }
com.cliffc.aa.type.Bits.dual
B dual()
Definition: Bits.java:368
com.cliffc.aa.HM.HM.Pair1.Pair1X.Pair1X
Pair1X(Type con)
Definition: HM.java:1019
com.cliffc.aa.HM.HM.Apply.p1
SB p1(SB sb)
Definition: HM.java:612
com.cliffc.aa.HM.HM.Apply.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:655
com.cliffc.aa.HM.HM.Ident.idt
T2 idt()
Definition: HM.java:435
com.cliffc.aa.HM.HM.Worklist.len
int len()
Definition: HM.java:292
com.cliffc.aa.HM.HM.Con.hm
boolean hm(Worklist work)
Definition: HM.java:413
com.cliffc.aa.HM.HM.Struct._flds
final Syntax[] _flds
Definition: HM.java:795
com.cliffc.aa.HM.HM.VStack.iterator
Iterator< T2 > iterator()
Definition: HM.java:330
com.cliffc.aa.HM.HM.Struct.str
SB str(SB sb)
Definition: HM.java:802
com.cliffc.aa.type.Type.NSCALR
static final Type NSCALR
Definition: Type.java:330
com.cliffc.aa.util.Ary.at
E at(int i)
Definition: Ary.java:25
com.cliffc.aa.HM.HM.Pair1
Definition: HM.java:1000
com.cliffc.aa.type.TypeFld.Access.Final
Final
Definition: TypeFld.java:112
com.cliffc.aa.HM.HM.PrimSyn.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:974
com.cliffc.aa.HM.HM.T2.reset
static void reset()
Definition: HM.java:2288
com.cliffc.aa.HM.HM.Pair.Pair
Pair()
Definition: HM.java:1037
com.cliffc.aa.HM.HM.T2.isa
boolean isa(String name)
Definition: HM.java:1357
com.cliffc.aa.HM.HM.T2.fresh_unify
boolean fresh_unify(T2 that, VStack nongen, Worklist work)
Definition: HM.java:1769
com.cliffc.aa.type.TypeFlds.get
TypeFld[] get()
Definition: TypeFlds.java:59
com.cliffc.aa.HM.HM.Let.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:573
com.cliffc.aa.HM.HM.EQ.var1
static T2 var1
Definition: HM.java:1106
com.cliffc.aa.HM.HM.IsEmpty
Definition: HM.java:1137
com.cliffc.aa.type.Bits.str
SB str(SB sb)
Definition: Bits.java:134
com.cliffc.aa.HM.HM.Pair1.var2
static T2 var2
Definition: HM.java:1002
com.cliffc.aa.type.BitsFun.EMPTY
static final BitsFun EMPTY
Definition: BitsFun.java:37
com.cliffc.aa.type.TypeObj.above_center
boolean above_center()
Definition: TypeObj.java:77
com.cliffc.aa.HM.HM.isDigit
static boolean isDigit(byte c)
Definition: HM.java:273
com.cliffc.aa.type.TypeFld.make_tup
static TypeFld make_tup(Type t, int order)
Definition: TypeFld.java:65
com.cliffc.aa.HM.HM.Syntax.find
T2 find()
Definition: HM.java:344
com.cliffc.aa.HM.HM.T2.occurs_in_type
boolean occurs_in_type(T2 x)
Definition: HM.java:1945
com.cliffc.aa.type.TypeFunPtr
Definition: TypeFunPtr.java:23
com.cliffc.aa.HM.HM.T2._name
String _name
Definition: HM.java:1298
com.cliffc.aa.HM.HM.Root
Definition: HM.java:735
com.cliffc.aa.HM.HM.T2.is_leaf
boolean is_leaf()
Definition: HM.java:1355
com.cliffc.aa.HM.HM.parse
static Root parse(String s)
Definition: HM.java:158
com.cliffc.aa.HM.HM.T2.meet_opens
boolean meet_opens(T2 that)
Definition: HM.java:1503
com.cliffc.aa.HM.HM.Ident._idx
int _idx
Definition: HM.java:429
com.cliffc.aa.HM.HM.If
Definition: HM.java:1066
com.cliffc.aa.util.Ary.push
E push(E e)
Add element in amortized constant time.
Definition: Ary.java:58
com.cliffc.aa.type.TypeTuple.make_args
static TypeTuple make_args(Type[] ts)
Definition: TypeTuple.java:106
com.cliffc.aa.HM.HM.Struct.p1
SB p1(SB sb)
Definition: HM.java:811
com.cliffc.aa.HM.HM.Dec.make
PrimSyn make()
Definition: HM.java:1248
com.cliffc.aa.HM.HM.T2.add_fld
boolean add_fld(String id, T2 fld, Worklist work)
Definition: HM.java:1697
com.cliffc.aa.type.BitsFun.make0
static BitsFun make0(int bit)
Definition: BitsFun.java:44
com.cliffc.aa.HM.HM.BUF
static byte[] BUF
Definition: HM.java:156
com.cliffc.aa.HM.HM.Lambda
Definition: HM.java:477
com.cliffc.aa.type.Type.isa
boolean isa(Type t)
Definition: Type.java:623
com.cliffc.aa.util.Util.find
static int find(int[] es, int e)
Definition: Util.java:6
com.cliffc.aa.HM.HM.Lambda.p1
SB p1(SB sb)
Definition: HM.java:505
com.cliffc.aa.HM.HM.T2.ODUPS
static final VBitSet ODUPS
Definition: HM.java:1933
com.cliffc.aa.HM.HM.Str.apply
Type apply(Syntax[] args)
Definition: HM.java:1263
com.cliffc.aa.type.TypeTuple.make_ret
static TypeTuple make_ret(Type trez)
Definition: TypeTuple.java:120
com.cliffc.aa.util.Util.eq
static boolean eq(String s0, String s1)
Definition: Util.java:16
com.cliffc.aa.type.TypeStruct.compute_hash
int compute_hash()
Definition: TypeStruct.java:66
com.cliffc.aa.type.Bits.clear
B clear(int bit)
Definition: Bits.java:255
com.cliffc.aa.type.Type.join
Type join(Type t)
Definition: Type.java:619
com.cliffc.aa.HM.HM.EQ.apply
Type apply(Syntax[] args)
Definition: HM.java:1109
com.cliffc.aa.HM.HM.Syntax.add_val_work
void add_val_work(Syntax child, Worklist work)
Definition: HM.java:365
com.cliffc.aa.util.SB.ii
SB ii(int i)
Definition: SB.java:44
com.cliffc.aa.HM.HM.Pair.apply
Type apply(Syntax[] args)
Definition: HM.java:1041
com.cliffc.aa.HM.HM.T2.CDUPS
static final HashMap< T2, T2 > CDUPS
Definition: HM.java:1961
com.cliffc.aa.HM.HM.T2.vput
boolean vput(T2 that, boolean progress)
Definition: HM.java:1895
com.cliffc.aa.type.Type.SCALAR
static final Type SCALAR
Definition: Type.java:328
com.cliffc
com.cliffc.aa.HM.HM.PrimSyn.add_val_work
void add_val_work(Syntax child, Worklist work)
Definition: HM.java:991
com.cliffc.aa.HM.HM.EQ.EQ
EQ()
Definition: HM.java:1107
com.cliffc.aa.HM.HM.Pair.var1
static T2 var1
Definition: HM.java:1036
com.cliffc.aa.type.Type.toString
final String toString()
Definition: Type.java:127
com.cliffc.aa.HM.HM.Pair.make
PrimSyn make()
Definition: HM.java:1040
com.cliffc.aa.util.SB.di
SB di(int i)
Definition: SB.java:46
com.cliffc.aa.HM.HM.T2.VARS
static final HashMap< T2, T2 > VARS
Definition: HM.java:1768
com.cliffc.aa.HM.HM.VStack.Iter.next
T2 next()
Definition: HM.java:335
com.cliffc.aa.type.Type.widen
Type widen()
Definition: Type.java:828
com.cliffc.aa.HM.HM.PrimSyn.str
SB str(SB sb)
Definition: HM.java:993
com.cliffc.aa.HM.HM.T2.meet_ids
String[] meet_ids(T2 that)
Definition: HM.java:1492
com.cliffc.aa.HM.HM.Con.p1
SB p1(SB sb)
Definition: HM.java:411
com.cliffc.aa.HM.HM.T2._p
SB _p(SB sb, VBitSet visit, VBitSet dups)
Definition: HM.java:2209
com.cliffc.aa.HM.HM.T2.make_fun
static T2 make_fun(BitsFun fidxs, T2... args)
Definition: HM.java:1324
com.cliffc.aa.HM.HM.Syntax.hm
abstract boolean hm(Worklist work)
com.cliffc.aa.HM.HM.Pair
Definition: HM.java:1034
com.cliffc.aa.type.TypeStruct.UF
static final NonBlockingHashMapLong< Type > UF
Definition: TypeStruct.java:475
com.cliffc.aa.HM.HM.Ident.p1
SB p1(SB sb)
Definition: HM.java:433
com.cliffc.aa.HM.HM.PrimSyn.STRP
static T2 STRP
Definition: HM.java:949
com.cliffc.aa.HM.HM.VStack.VStack
VStack(VStack par, T2 nongen)
Definition: HM.java:312
com.cliffc.aa.HM.HM.T2._cycle_equals
boolean _cycle_equals(T2 t)
Definition: HM.java:1968
com.cliffc.aa.type.TypeFld
Definition: TypeFld.java:12
com.cliffc.aa.HM.HM.Con
Definition: HM.java:407
com.cliffc.aa.type.Type.XSCALAR
static final Type XSCALAR
Definition: Type.java:329
com.cliffc.aa.HM.HM.IsEmpty.IsEmpty
IsEmpty()
Definition: HM.java:1139
com.cliffc.aa.HM.HM.PrimSyn
Definition: HM.java:948
com.cliffc.aa.HM.HM.T2.union_err
boolean union_err(T2 that, Worklist work, String msg)
Definition: HM.java:1757
com.cliffc.aa.util
Definition: AbstractEntry.java:1
com.cliffc.aa.HM.HM.Dec.name
String name()
Definition: HM.java:1246
com.cliffc.aa.HM.HM.Worklist._ary
final Ary< Syntax > _ary
Definition: HM.java:290
com.cliffc.aa.type.TypeInt
Definition: TypeInt.java:9
com.cliffc.aa.HM.HM.VStack
Definition: HM.java:308
com.cliffc.aa.HM.HM.PrimSyn.FLT64
static T2 FLT64
Definition: HM.java:949
com.cliffc.aa.HM.HM.NotNil.name
String name()
Definition: HM.java:1153
com.cliffc.aa.HM.HM.Syntax.val
abstract Type val(Worklist work)
com.cliffc.aa.type.BitsFun.init0
static void init0()
Definition: BitsFun.java:28
com.cliffc.aa.HM.HM.Factor
Definition: HM.java:1274
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.HM.HM.Lambda._types
final Type[] _types
Definition: HM.java:483
com.cliffc.aa.util.NonBlockingHashMapLong.clear
void clear()
Removes all of the mappings from this map.
Definition: NonBlockingHashMapLong.java:332
com.cliffc.aa.HM.HM.Root.flow_type
Type flow_type()
Definition: HM.java:775
com.cliffc.aa.type.TypeFunSig.make
static TypeFunSig make(String[] args, TypeTuple formals, TypeTuple ret)
Definition: TypeFunSig.java:71
com.cliffc.aa.HM.HM.T2.UPDATE_VISIT
static final VBitSet UPDATE_VISIT
Definition: HM.java:2117
com.cliffc.aa.HM.HM.T2.is_struct
boolean is_struct()
Definition: HM.java:1361
com.cliffc.aa.HM.HM.Add.name
String name()
Definition: HM.java:1228
com.cliffc.aa.HM.HM.T2._fresh
T2 _fresh(VStack nongen)
Definition: HM.java:1904
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.HM.T2.push_update
T2 push_update(Syntax a)
Definition: HM.java:2119
com.cliffc.aa.util.Ary
Definition: Ary.java:11
com.cliffc.aa.HM.HM.IsEmpty.make
PrimSyn make()
Definition: HM.java:1140
com.cliffc.aa.HM.HM.If.apply
Type apply(Syntax[] args)
Definition: HM.java:1087
com.cliffc.aa.type.BitsFun.FULL
static final BitsFun FULL
Definition: BitsFun.java:33
com.cliffc.aa.type.BitsAlias
Definition: BitsAlias.java:8
com.cliffc.aa.HM.HM.Pair1.apply
Type apply(Syntax[] args)
Definition: HM.java:1008
com.cliffc.aa.HM.HM.Pair1.Pair1
Pair1()
Definition: HM.java:1004
com.cliffc.aa.type.Type.meet_nil
Type meet_nil(Type nil)
Definition: Type.java:904
com.cliffc.aa.HM.HM.PrimSyn.BOOL
static T2 BOOL
Definition: HM.java:949
com.cliffc.aa.HM.HM.Apply._args
final Syntax[] _args
Definition: HM.java:604
com.cliffc.aa.HM.HM.T2.unify_nil
boolean unify_nil(T2 that, Worklist work)
Definition: HM.java:1559
com.cliffc.aa.HM.HM.isAlpha0
static boolean isAlpha0(byte c)
Definition: HM.java:274
com.cliffc.aa.type.TypeTuple
Definition: TypeTuple.java:11
com.cliffc.aa.HM.HM.Syntax.p2
abstract SB p2(SB sb, VBitSet dups)
com.cliffc.aa.HM.HM.Str.make
PrimSyn make()
Definition: HM.java:1262
com.cliffc.aa.HM.HM.Let.str
SB str(SB sb)
Definition: HM.java:569
com.cliffc.aa.type.TypeFld.NO_DISP
static final TypeFld NO_DISP
Definition: TypeFld.java:170
com.cliffc.aa.HM.HM.Lambda.Lambda
Lambda(Syntax body, String... args)
Definition: HM.java:486
com.cliffc.aa.HM.HM.T2.fresh_base
boolean fresh_base(T2 that, Worklist work)
Definition: HM.java:1719
com.cliffc.aa.HM.HM.Add.make
PrimSyn make()
Definition: HM.java:1230
com.cliffc.aa.type.TypeFunPtr._fidxs
BitsFun _fidxs
Definition: TypeFunPtr.java:26
com.cliffc.aa.type.TypeInt.con
static TypeInt con(long con)
Definition: TypeInt.java:37
com.cliffc.aa.HM.HM.Root.NARGS
static final Syntax[] NARGS
Definition: HM.java:736
com.cliffc.aa.HM.HM.Lambda._targs
final T2[] _targs
Definition: HM.java:482
com.cliffc.aa.HM.HM.Root.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:740
com.cliffc.aa.HM.HM.Let.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM.java:593
com.cliffc.aa.HM.HM
Definition: HM.java:84
com.cliffc.aa.HM.HM.T2.walk_types_out
Type walk_types_out(Type t)
Definition: HM.java:2061
com.cliffc.aa.HM.HM.Pair1.name
String name()
Definition: HM.java:1001
com.cliffc.aa.HM.HM.T2.as_flow
Type as_flow()
Definition: HM.java:1427
com.cliffc.aa.HM.HM.T2.make_leaf
static T2 make_leaf()
Definition: HM.java:1321
com.cliffc.aa.HM.HM.Dec
Definition: HM.java:1245
com.cliffc.aa.util.VBitSet.clr
VBitSet clr()
Definition: VBitSet.java:9
com.cliffc.aa.type.TypeFlds
Definition: TypeFlds.java:8
com.cliffc.aa.HM.HM.NotNil.NotNil
NotNil()
Definition: HM.java:1154
com.cliffc.aa.HM.HM.Syntax.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM.java:377
com.cliffc.aa.type.Type.ANY
static final Type ANY
Definition: Type.java:325
com.cliffc.aa.HM.HM.T2._occurs_in_type
boolean _occurs_in_type(T2 x)
Definition: HM.java:1934
com.cliffc.aa.HM.HM.Syntax._flow
Type _flow
Definition: HM.java:351
com.cliffc.aa.HM.HM.Lambda.prep_lookup_deps
void prep_lookup_deps(Ident id)
Definition: HM.java:554
com.cliffc.aa.type.TypeStruct.install_cyclic
TypeStruct install_cyclic(Ary< Type > reachs)
Definition: TypeStruct.java:422
com.cliffc.aa.HM.HM.T2.args
T2 args(int i)
Definition: HM.java:1415
com.cliffc.aa.type.BitsAlias.new_alias
static int new_alias(int par)
Definition: BitsAlias.java:75
com.cliffc.aa.HM.HM.Str.name
String name()
Definition: HM.java:1260
com.cliffc.aa.HM.HM.VStack._d
final int _d
Definition: HM.java:311
com.cliffc.aa.HM.HM.Root.widen
static Type widen(T2 t2)
Definition: HM.java:743
com.cliffc.aa.HM.HM.T2.add_deps_work_impl
void add_deps_work_impl(Worklist work)
Definition: HM.java:2133
com.cliffc.aa.type.Type.meet
final Type meet(Type t)
Definition: Type.java:412
com.cliffc.aa.HM.HM.Let.hm
boolean hm(Worklist work)
Definition: HM.java:572
com.cliffc.aa.type.TypeStruct
A memory-based collection of optionally named fields.
Definition: TypeStruct.java:50
com.cliffc.aa.type.TypeFld.make
static TypeFld make(String fld, Type t, int order)
Definition: TypeFld.java:58
com.cliffc.aa.AA.unimpl
static RuntimeException unimpl()
Definition: AA.java:10
com.cliffc.aa.type.Bits.test
static boolean test(long[] bits, int i)
Definition: Bits.java:224
com.cliffc.aa.type.Type.str
SB str(SB sb, VBitSet dups, TypeMem mem, boolean debug)
Definition: Type.java:131
com.cliffc.aa.HM.HM.DO_HM
static final boolean DO_HM
Definition: HM.java:91
com.cliffc.aa.type.TypeMemPtr._obj
TypeObj _obj
Definition: TypeMemPtr.java:26
com.cliffc.aa.HM.HM.Mul.make
PrimSyn make()
Definition: HM.java:1210
com.cliffc.aa.HM.HM.T2.toString
String toString()
Definition: HM.java:2162
com.cliffc.aa.type.Type.intern_check
static boolean intern_check()
Definition: Type.java:212
com.cliffc.aa.HM.HM.Con.more_work
boolean more_work(Worklist work)
Definition: HM.java:422
com.cliffc.aa.type.TypeStruct.at
Type at(int idx)
Definition: TypeStruct.java:1013
com.cliffc.aa.HM.HM.Pair1.Pair1X.var2
static T2 var2
Definition: HM.java:1018
com.cliffc.aa.HM.HM.T2.make_struct
static T2 make_struct(BitsAlias aliases, String[] ids, T2[] flds, boolean open)
Definition: HM.java:1326
com.cliffc.aa.HM.HM.T2.FIDX_VISIT
static final VBitSet FIDX_VISIT
Definition: HM.java:2098
com.cliffc.aa.HM.HM.isAlpha1
static boolean isAlpha1(byte c)
Definition: HM.java:275
com.cliffc.aa.HM.HM.T2.push_update
T2 push_update(Ary< Syntax > as)
Definition: HM.java:2118
com.cliffc.aa.HM.HM.ID
static final SB ID
Definition: HM.java:239
com.cliffc.aa.HM.HM.Con.p2
SB p2(SB sb, VBitSet dups)
Definition: HM.java:412
com.cliffc.aa.HM.HM.Field.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:917
com.cliffc.aa.HM.HM.T2.FIDXS
static BitsFun FIDXS
Definition: HM.java:2099
com.cliffc.aa.util.SB.unchar
SB unchar()
Definition: SB.java:58
Iterable
com.cliffc.aa.HM.HM.PrimSyn.hm
boolean hm(Worklist work)
Definition: HM.java:978
com.cliffc.aa.HM.HM.Worklist.push
void push(Syntax s)
Definition: HM.java:293
com.cliffc.aa.HM.HM.Lambda.str
SB str(SB sb)
Definition: HM.java:500
com.cliffc.aa.type.Type.ALL
static final Type ALL
Definition: Type.java:324
com.cliffc.aa.HM.HM.Pair1.Pair1X.make
PrimSyn make()
Definition: HM.java:1023
com.cliffc.aa.HM.HM.PrimSyn.WORK
static Worklist WORK
Definition: HM.java:950
com.cliffc.aa.HM.HM.T2.make_base
static T2 make_base(Type flow)
Definition: HM.java:1323
com.cliffc.aa.HM.HM.Factor.Factor
Factor()
Definition: HM.java:1276
com.cliffc.aa.HM.HM.Apply
Definition: HM.java:602
com.cliffc.aa.type.BitsAlias.REC
static final int REC
Definition: BitsAlias.java:25
com.cliffc.aa.HM.HM.Let.add_val_work
void add_val_work(Syntax child, Worklist work)
Definition: HM.java:580
com.cliffc.aa.HM.HM.T2._flow
Type _flow
Definition: HM.java:1309
com.cliffc.aa.util.Ary.asAry
E[] asAry()
Definition: Ary.java:172
com.cliffc.aa.HM.HM.Add.apply
Type apply(Syntax[] args)
Definition: HM.java:1231
com.cliffc.aa.HM.HM.toString
String toString()
Definition: HM.java:157
com.cliffc.aa.util.VBitSet.tset
boolean tset(int idx)
Definition: VBitSet.java:7
com.cliffc.aa.HM.HM.Struct.p2
SB p2(SB sb, VBitSet dups)
Definition: HM.java:812
com.cliffc.aa.HM.HM.T2.is_base
boolean is_base()
Definition: HM.java:1358
com.cliffc.aa.HM.HM.Lambda.FUNS
static final NonBlockingHashMapLong< Lambda > FUNS
Definition: HM.java:479
com.cliffc.aa.HM.HM.T2.push_update_impl
void push_update_impl(Syntax a)
Definition: HM.java:2120
com.cliffc.aa.HM.HM.Triple.var2
static T2 var2
Definition: HM.java:1053
com.cliffc.aa.HM.HM.Apply._fun
final Syntax _fun
Definition: HM.java:603
com.cliffc.aa.HM.HM.Con.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:416
com.cliffc.aa.HM.HM.Lambda.more_work
boolean more_work(Worklist work)
Definition: HM.java:558
com.cliffc.aa.HM.HM.Mul.name
String name()
Definition: HM.java:1208
com.cliffc.aa.HM.HM.T2.find
T2 find(int uid)
Definition: HM.java:2278
com.cliffc.aa.HM.HM.PrimSyn.PrimSyn
PrimSyn(T2 ...t2s)
Definition: HM.java:967
com.cliffc.aa.HM.HM.VStack._par
final VStack _par
Definition: HM.java:309
com.cliffc.aa.HM.HM.T2.T2
T2(@NotNull String name, T2 @NotNull ... args)
Definition: HM.java:1349
com.cliffc.aa.type.TypeInt.INT64
static final TypeInt INT64
Definition: TypeInt.java:39
com.cliffc.aa.HM.HM.Worklist.clear
void clear()
Definition: HM.java:298
com.cliffc.aa.HM.HM.VStack.toString
String toString()
Definition: HM.java:317
com.cliffc.aa.HM.HM.Let.Let
Let(String arg0, Syntax def, Syntax body)
Definition: HM.java:568
com.cliffc.aa.HM.HM.Worklist._cnt
int _cnt
Definition: HM.java:289
com.cliffc.aa.HM.HM.Let._targ
T2 _targ
Definition: HM.java:567
com.cliffc.aa.HM.HM.Syntax._par
Syntax _par
Definition: HM.java:341
com.cliffc.aa.type.TypeObj
Definition: TypeObj.java:15
com.cliffc.aa.HM.HM.Syntax.p1
abstract SB p1(SB sb)
com.cliffc.aa.HM.HM.T2.CNT
static int CNT
Definition: HM.java:1292
com.cliffc.aa.type.TypeFlt.con
static Type con(double con)
Definition: TypeFlt.java:36
com.cliffc.aa.HM.HM.Syntax.p0
final SB p0(SB sb, VBitSet dups)
Definition: HM.java:394
com.cliffc.aa.HM.HM.Ident._def
Syntax _def
Definition: HM.java:428
com.cliffc.aa.HM.HM.T2.walk_types_in
Type walk_types_in(Type t)
Definition: HM.java:2005
com.cliffc.aa.HM.HM.Con.val
Type val(Worklist work)
Definition: HM.java:414
com.cliffc.aa.type.Type.is_con
boolean is_con()
Definition: Type.java:776
com.cliffc.aa.HM.HM.Lambda.add_val_work
void add_val_work(Syntax child, Worklist work)
Definition: HM.java:544
com.cliffc.aa.HM.HM.Let.p1
SB p1(SB sb)
Definition: HM.java:570
com.cliffc.aa.HM.HM.Ident.val
Type val(Worklist work)
Definition: HM.java:450
com.cliffc.aa.HM.HM.Pair1.Pair1X.apply
Type apply(Syntax[] args)
Definition: HM.java:1025
com.cliffc.aa.type.Type.above_center
boolean above_center()
Definition: Type.java:741
com.cliffc.aa.HM.HM.T2._as_flow
Type _as_flow()
Definition: HM.java:1434
com.cliffc.aa.util.NonBlockingHashMapLong.get
final TypeV get(long key)
Returns the value to which the specified key is mapped, or.
Definition: NonBlockingHashMapLong.java:368
com.cliffc.aa.HM.HM.T2.p
String p()
Definition: HM.java:2205
com.cliffc.aa.HM.HM.T2._alias
BitsAlias _alias
Definition: HM.java:1312
com.cliffc.aa.HM.HM.Struct.Struct
Struct(String[] ids, Syntax[] flds)
Definition: HM.java:796
com.cliffc.aa.HM.HM.Ident._name
final String _name
Definition: HM.java:427
com.cliffc.aa.HM.HM.T2.p
String p(VBitSet dups)
Definition: HM.java:2208
com.cliffc.aa.HM.HM.T2.cycle_equals
boolean cycle_equals(T2 t)
Definition: HM.java:1962
com.cliffc.aa.HM.HM.Pair1.make
PrimSyn make()
Definition: HM.java:1007
com.cliffc.aa.type.TypeObj.is_con
boolean is_con()
Definition: TypeObj.java:79
com.cliffc.aa.HM.HM.Apply.more_work
boolean more_work(Worklist work)
Definition: HM.java:726
com.cliffc.aa.HM.HM.Field.val
Type val(Worklist work)
Definition: HM.java:922
com.cliffc.aa.HM.HM.Mul.Mul
Mul()
Definition: HM.java:1209
com.cliffc.aa.HM.HM.If.make
PrimSyn make()
Definition: HM.java:1069
com.cliffc.aa.HM.HM.Con._con
final Type _con
Definition: HM.java:408
com.cliffc.aa.HM.HM.T2._find0
T2 _find0()
Definition: HM.java:1379
com.cliffc.aa.HM.HM.Struct._ids
final String[] _ids
Definition: HM.java:794
com.cliffc.aa.type.Type.RECURSIVE_MEET
static int RECURSIVE_MEET
Definition: Type.java:163
com.cliffc.aa.HM.HM.Pair.name
String name()
Definition: HM.java:1035
com.cliffc.aa.HM.HM.Syntax
Definition: HM.java:340
com.cliffc.aa.HM.HM.Syntax._nongen
VStack _nongen
Definition: HM.java:342
com.cliffc.aa.HM.HM.T2._find_nil
T2 _find_nil()
Definition: HM.java:1389
com.cliffc.aa.HM.HM.If.name
String name()
Definition: HM.java:1067
com.cliffc.aa.HM.HM.Struct
Definition: HM.java:792
com.cliffc.aa.util.NonBlockingHashMapLong.putIfAbsent
TypeV putIfAbsent(long key, TypeV val)
Atomically, do a put if-and-only-if the key is not mapped.
Definition: NonBlockingHashMapLong.java:286
com.cliffc.aa.HM.HM.number
static Syntax number()
Definition: HM.java:248
com.cliffc.aa.HM.HM.Syntax._hmt
T2 _hmt
Definition: HM.java:343
com.cliffc.aa.HM.HM.skipWS
static byte skipWS()
Definition: HM.java:268
com.cliffc.aa.HM.HM.Struct.more_work
boolean more_work(Worklist work)
Definition: HM.java:880
com.cliffc.aa.HM.HM.Pair1.Pair1X._con
final Type _con
Definition: HM.java:1016
com.cliffc.aa.HM.HM.Syntax.add_hm_work
abstract void add_hm_work(Worklist work)
com.cliffc.aa.HM.HM.require
static void require(String s)
Definition: HM.java:278
com.cliffc.aa.HM.HM.Let.p2
SB p2(SB sb, VBitSet dups)
Definition: HM.java:571
com.cliffc.aa.HM.HM.Worklist.has
boolean has(Syntax s)
Definition: HM.java:296
com.cliffc.aa.HM.HM.Syntax.more_work
abstract boolean more_work(Worklist work)
com.cliffc.aa.HM.HM.Let
Definition: HM.java:564
com.cliffc.aa.util.Util
Definition: Util.java:5
com.cliffc.aa.HM.HM.Field.more_work
boolean more_work(Worklist work)
Definition: HM.java:941
com.cliffc.aa.HM.HM.Lambda.p2
SB p2(SB sb, VBitSet dups)
Definition: HM.java:515
com.cliffc.aa.HM.HM.Field.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:937
com.cliffc.aa.HM.HM.Triple.var3
static T2 var3
Definition: HM.java:1053
com.cliffc.aa.HM.HM.Ident.Ident
Ident(String name)
Definition: HM.java:431
com.cliffc.aa.HM.HM.Field.str
SB str(SB sb)
Definition: HM.java:894
com.cliffc.aa.HM.HM.EQ.make
PrimSyn make()
Definition: HM.java:1108
com.cliffc.aa.HM.HM.T2.is_err
boolean is_err()
Definition: HM.java:1362
com.cliffc.aa.HM.HM.Ident.str
SB str(SB sb)
Definition: HM.java:432
com.cliffc.aa.HM.HM.Apply.val
Type val(Worklist work)
Definition: HM.java:661
com.cliffc.aa.HM.HM.Ident.more_work
boolean more_work(Worklist work)
Definition: HM.java:473
com.cliffc.aa.HM.HM.Pair1.var1
static T2 var1
Definition: HM.java:1002
com.cliffc.aa.type.TypeStruct.reachable
Ary< Type > reachable()
Definition: TypeStruct.java:779
com.cliffc.aa.type.Type.must_nil
boolean must_nil()
Definition: Type.java:845
com.cliffc.aa.HM.HM.isWS
static boolean isWS(byte c)
Definition: HM.java:272
com.cliffc.aa.type.Bits.meet_nil
B meet_nil()
Definition: Bits.java:212
com.cliffc.aa.HM.HM.T2.is_tuple
boolean is_tuple()
Definition: HM.java:2269
com.cliffc.aa.HM.HM.Struct._alias
final int _alias
Definition: HM.java:793
com.cliffc.aa.type.TypeStr.con
static TypeStr con(String con)
Definition: TypeStr.java:42
com.cliffc.aa.HM.HM.Let.val
Type val(Worklist work)
Definition: HM.java:579
com.cliffc.aa.HM.HM.NotNil
Definition: HM.java:1152
com.cliffc.aa.type.TypeFunPtr.make
static TypeFunPtr make(BitsFun fidxs, int nargs, Type disp)
Definition: TypeFunPtr.java:67
com.cliffc.aa.HM.HM.Syntax.more_work_impl
final boolean more_work_impl(Worklist work)
Definition: HM.java:381
com.cliffc.aa.HM.HM.require
static void require(char c)
Definition: HM.java:276
com.cliffc.aa.HM.HM.Ident
Definition: HM.java:426
com.cliffc.aa.HM.HM.EQ.name
String name()
Definition: HM.java:1105
com.cliffc.aa.HM.HM.Ident.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:442
com.cliffc.aa.HM.HM.Mul.apply
Type apply(Syntax[] args)
Definition: HM.java:1211
com.cliffc.aa.HM.HM.T2.meet_fidxs
BitsFun meet_fidxs(T2 that)
Definition: HM.java:1482
com.cliffc.aa.HM.HM.Triple.var1
static T2 var1
Definition: HM.java:1053
com.cliffc.aa.HM.HM.T2._args
T2[] _args
Definition: HM.java:1301
com.cliffc.aa.HM.HM.Syntax.prep_tree_impl
final void prep_tree_impl(Syntax par, VStack nongen, Worklist work, T2 t)
Definition: HM.java:370
com.cliffc.aa.HM.HM.EQ0.make
PrimSyn make()
Definition: HM.java:1124
com.cliffc.aa.HM.HM.T2._find
T2 _find(int uid, VBitSet visit)
Definition: HM.java:2279
com.cliffc.aa.HM.HM.T2.unify
boolean unify(T2 that, Worklist work)
Definition: HM.java:1604
com.cliffc.aa.HM.HM.VStack.Iter
Definition: HM.java:331
com.cliffc.aa.HM.HM.id
static String id()
Definition: HM.java:240
com.cliffc.aa.type.TypeStr
Definition: TypeStr.java:14
com.cliffc.aa.HM.HM.Lambda.val
Type val(Worklist work)
Definition: HM.java:541
com.cliffc.aa.type.BitsAlias.EMPTY
static BitsAlias EMPTY
Definition: BitsAlias.java:27
com.cliffc.aa.HM.HM.T2.base_states
int base_states()
Definition: HM.java:1515
com.cliffc.aa.HM.HM.T2
Definition: HM.java:1291
com.cliffc.aa.HM.HM.T2.DUPS
static final HashMap< Long, T2 > DUPS
Definition: HM.java:1603
com.cliffc.aa.HM.HM.T2._open
boolean _open
Definition: HM.java:1314
com.cliffc.aa.HM.HM.T2._err
String _err
Definition: HM.java:1315
com.cliffc.aa.util.VBitSet
Definition: VBitSet.java:5
com.cliffc.aa.HM.HM.PrimSyn.TRIPLE_ALIAS
static int TRIPLE_ALIAS
Definition: HM.java:951
com.cliffc.aa.HM.HM.Syntax.str
abstract SB str(SB sb)
com.cliffc.aa.type.TypeStruct.tups
static TypeFld[] tups(Type t1, Type t2)
Definition: TypeStruct.java:186
com.cliffc.aa.HM.HM.Let.more_work
boolean more_work(Worklist work)
Definition: HM.java:596
com.cliffc.aa.HM.HM.Lambda.apply
Type apply(Syntax[] args)
Definition: HM.java:543
com.cliffc.aa.type.BitsFun
Definition: BitsFun.java:7
com.cliffc.aa.HM.HM.require
static< T > T require(char c, T t)
Definition: HM.java:277
com.cliffc.aa.HM.HM.VStack.nongen
T2 nongen()
Definition: HM.java:313
com.cliffc.aa.HM.HM.VStack.str
SB str(SB sb, VBitSet dups)
Definition: HM.java:325
com.cliffc.aa.HM.HM.DEBUG_LEAKS
static final boolean DEBUG_LEAKS
Definition: HM.java:88
com.cliffc.aa.HM.HM.T2._cycle_equals_struct
boolean _cycle_equals_struct(T2 t)
Definition: HM.java:1992
com.cliffc.aa.type.BitsAlias.init0
static void init0()
Definition: BitsAlias.java:63
NotNull
com.cliffc.aa.util.SB
Tight/tiny StringBuilder wrapper.
Definition: SB.java:8
com.cliffc.aa.HM.HM.Pair1.PAIR1S
static HashMap< Type, Pair1X > PAIR1S
Definition: HM.java:1003
com.cliffc.aa.HM.HM.Worklist.addAll
void addAll(Ary<? extends Syntax > ss)
Definition: HM.java:297
com.cliffc.aa.HM.HM.Struct.hm
boolean hm(Worklist work)
Definition: HM.java:817
com.cliffc.aa.HM.HM.PrimSyn.more_work
boolean more_work(Worklist work)
Definition: HM.java:992
com.cliffc.aa.HM.HM.Root.str
SB str(SB sb)
Definition: HM.java:738
com.cliffc.aa.type.Type.NIL
static final Type NIL
Definition: Type.java:332
com.cliffc.aa.HM.HM.Ident.hm
boolean hm(Worklist work)
Definition: HM.java:439
com.cliffc.aa.HM.HM.Apply.WDUPS
static final NonBlockingHashMapLong< String > WDUPS
Definition: HM.java:660
com.cliffc.aa.HM.HM.PRIMSYNS
static final HashMap< String, PrimSyn > PRIMSYNS
Definition: HM.java:86
com.cliffc.aa.HM.HM.EQ0
Definition: HM.java:1121
com.cliffc.aa.HM.HM.T2.T2
T2(@NotNull String name)
Definition: HM.java:1348
com.cliffc.aa.HM.HM.Field.p1
SB p1(SB sb)
Definition: HM.java:895
com.cliffc.aa.HM.HM.T2._get_dups
VBitSet _get_dups(VBitSet visit, VBitSet dups)
Definition: HM.java:2149
com.cliffc.aa.HM.HM.Lambda.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:548
com.cliffc.aa.HM.HM.Root.add_sig
static Type add_sig(Type t)
Definition: HM.java:776
com.cliffc.aa.HM.HM.Worklist._work
final HashSet< Syntax > _work
Definition: HM.java:291
com.cliffc.aa.type.TypeFld.malloc
static TypeFld malloc(String fld, Type t, Access access, int order)
Definition: TypeFld.java:53
com.cliffc.aa.HM.HM.Syntax.p
String p()
Definition: HM.java:393
com.cliffc.aa.HM.HM.T2._can_be_HM_base
boolean _can_be_HM_base(T2 that, Type that_flow)
Definition: HM.java:1749
com.cliffc.aa.HM.HM.Triple.name
String name()
Definition: HM.java:1052
com.cliffc.aa.HM.HM.Triple
Definition: HM.java:1051
com.cliffc.aa.HM.HM.term
static Syntax term()
Definition: HM.java:166
com.cliffc.aa.HM.HM.hm
static Root hm(String sprog)
Definition: HM.java:94
com.cliffc.aa.AA
an implementation of language AA
Definition: AA.java:9
com.cliffc.aa.HM.HM.T2._deps
Ary< Syntax > _deps
Definition: HM.java:1318
com.cliffc.aa.HM.HM.Field.p2
SB p2(SB sb, VBitSet dups)
Definition: HM.java:896
com.cliffc.aa.HM.HM.Lambda.targ
T2 targ(int i)
Definition: HM.java:516
com.cliffc.aa.HM.HM.Worklist
Definition: HM.java:288
com.cliffc.aa.type.TypeStruct.len
int len(TypeStruct tt)
Definition: TypeStruct.java:865
com.cliffc.aa.HM.HM.PrimSyn.p1
SB p1(SB sb)
Definition: HM.java:994
com.cliffc.aa.type.TypeStruct.approx
TypeStruct approx(int cutoff, int alias)
Definition: TypeStruct.java:477
com.cliffc.aa.HM.HM.VStack.Iter.Iter
Iter()
Definition: HM.java:333
com.cliffc.aa.HM.HM.Apply.hm
boolean hm(Worklist work)
Definition: HM.java:621
com.cliffc.aa.HM.HM.Str
Definition: HM.java:1259
com.cliffc.aa.HM.HM.T2.fresh
T2 fresh()
Definition: HM.java:1898
com.cliffc.aa.type.TypeStruct.fld_find
int fld_find(String fld)
Definition: TypeStruct.java:1038
com.cliffc.aa.HM.HM.If.If
If()
Definition: HM.java:1068
com.cliffc.aa.HM.HM.PrimSyn.make
abstract PrimSyn make()
com.cliffc.aa.HM.HM.T2.VCNT
static int VCNT
Definition: HM.java:2206
com.cliffc.aa.HM.HM.VStack.Iter.hasNext
boolean hasNext()
Definition: HM.java:334
com.cliffc.aa.HM.HM.Pair.var2
static T2 var2
Definition: HM.java:1036
com.cliffc.aa.HM.HM.T2.copy
T2 copy()
Definition: HM.java:1335
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.util.SB.nl
SB nl()
Definition: SB.java:48
com.cliffc.aa.HM.HM.Ident.p2
SB p2(SB sb, VBitSet dups)
Definition: HM.java:434
com.cliffc.aa.type.BitsAlias.make0
static BitsAlias make0(int bit)
Definition: BitsAlias.java:72
com.cliffc.aa.HM.HM.T2.fput
Type fput(final Type t)
Definition: HM.java:2056
com.cliffc.aa.HM.HM.T2.no_uf
boolean no_uf()
Definition: HM.java:1356
com.cliffc.aa.type.TypeStruct.fld
TypeFld fld(int idx)
Definition: TypeStruct.java:1012
com.cliffc.aa.HM.HM.Str.Str
Str()
Definition: HM.java:1261
com.cliffc.aa.HM.HM.Worklist.toString
String toString()
Definition: HM.java:303
com.cliffc.aa.type.Type._uid
int _uid
Definition: Type.java:96
com.cliffc.aa.type.BitsFun.ANY
static final BitsFun ANY
Definition: BitsFun.java:34
com.cliffc.aa.HM.HM.T2._fresh_unify_struct
boolean _fresh_unify_struct(T2 that, VStack nongen, Worklist work)
Definition: HM.java:1855
com.cliffc.aa.HM.HM.Apply.str
SB str(SB sb)
Definition: HM.java:606
com.cliffc.aa.HM.HM.T2.make_err
static T2 make_err(String s)
Definition: HM.java:1333
com.cliffc.aa.type.TypeStruct.make_from
TypeStruct make_from(String name)
Definition: TypeStruct.java:215
com.cliffc.aa.type.BitsAlias.STRBITS
static BitsAlias STRBITS
Definition: BitsAlias.java:27
com.cliffc.aa.HM.HM.Factor.name
String name()
Definition: HM.java:1275
com.cliffc.aa.HM.HM.Field._rec
final Syntax _rec
Definition: HM.java:892
com.cliffc.aa.HM.HM.Lambda._args
final String[] _args
Definition: HM.java:480
com.cliffc.aa.HM.HM.Struct.val
Type val(Worklist work)
Definition: HM.java:860
Cloneable
com.cliffc.aa.HM.HM.Pair1.Pair1X
Definition: HM.java:1015
com.cliffc.aa.HM.HM.PrimSyn.name
abstract String name()
com.cliffc.aa.HM.HM.T2.str
static SB str(SB sb, VBitSet visit, T2 t, VBitSet dups)
Definition: HM.java:2202
com.cliffc.aa.util.SB.p
SB p(String s)
Definition: SB.java:13
com.cliffc.aa.HM.HM.T2.meet_flow
Type meet_flow(T2 that)
Definition: HM.java:1477
com.cliffc.aa.HM.HM.Field.hm
boolean hm(Worklist work)
Definition: HM.java:897
com.cliffc.aa.HM.HM.Lambda._fidx
final int _fidx
Definition: HM.java:484
com.cliffc.aa.HM.HM.Con.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:415
com.cliffc.aa.type.TypeInt.FALSE
static final Type FALSE
Definition: TypeInt.java:45
com.cliffc.aa.HM.HM.Syntax.prep_tree
abstract int prep_tree(Syntax par, VStack nongen, Worklist work)
com.cliffc.aa.HM.HM.Field
Definition: HM.java:890
com.cliffc.aa.HM.HM.T2.nongen_in
boolean nongen_in(VStack vs)
Definition: HM.java:1950
com.cliffc.aa.HM.HM.Lambda._body
final Syntax _body
Definition: HM.java:481
com.cliffc.aa.HM.HM.NotNil.apply
Type apply(Syntax[] args)
Definition: HM.java:1199
com.cliffc.aa.type.TypeFunSig
Definition: TypeFunSig.java:10
com.cliffc.aa.type.BitsFun.reset_to_init0
static void reset_to_init0()
Definition: BitsFun.java:29
com.cliffc.aa.HM.HM.T2.is_nilable
boolean is_nilable()
Definition: HM.java:1359
com.cliffc.aa.HM.HM.DO_GCP
static final boolean DO_GCP
Definition: HM.java:92
com.cliffc.aa.HM.HM.T2.find
T2 find()
Definition: HM.java:1374
com.cliffc.aa.type.Type.dual
final T dual()
Definition: Type.java:361
com.cliffc.aa.HM.HM.PrimSyn.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:988
com.cliffc.aa.HM.HM.EQ0.name
String name()
Definition: HM.java:1122
com.cliffc.aa.HM.HM.T2.make_struct
static T2 make_struct(BitsAlias aliases, String[] ids, T2[] flds)
Definition: HM.java:1325
com.cliffc.aa.HM.HM.Ident.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:453
com.cliffc.aa.HM.HM.PrimSyn.reset
static void reset()
Definition: HM.java:952
com.cliffc.aa.HM.HM.PrimSyn.INT64
static T2 INT64
Definition: HM.java:949
com.cliffc.aa.HM.HM.Apply.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:720
com.cliffc.aa.HM.HM.Triple.Triple
Triple()
Definition: HM.java:1054
com.cliffc.aa.type.TypeStruct.make
static TypeStruct make(String fld_name, Type t)
Definition: TypeStruct.java:190
com.cliffc.aa.util.NonBlockingHashMapLong
A lock-free alternate implementation of java.util.concurrent.ConcurrentHashMap with primitive long ke...
Definition: NonBlockingHashMapLong.java:91
com.cliffc.aa.HM.HM.Root.val
Type val(Worklist work)
Definition: HM.java:744
com.cliffc.aa.HM.HM.Field._id
final String _id
Definition: HM.java:891
com.cliffc.aa.HM.HM.T2._unify_struct
void _unify_struct(T2 that, Worklist work)
Definition: HM.java:1667
com.cliffc.aa.type.TypeStruct.shrink
static TypeStruct shrink(Ary< Type > reaches, TypeStruct tstart)
Definition: TypeStruct.java:657
com.cliffc.aa.HM.HM.Ident._idt
T2 _idt
Definition: HM.java:430
com.cliffc.aa.HM.HM.Struct.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:856
com.cliffc.aa.HM.HM.T2.VNAMES
static final HashMap< T2, Integer > VNAMES
Definition: HM.java:2207
com.cliffc.aa.HM.HM.EQ0.apply
Type apply(Syntax[] args)
Definition: HM.java:1125
com.cliffc.aa.HM.HM.Syntax.debug_find
T2 debug_find()
Definition: HM.java:348
com.cliffc.aa.HM.HM.IsEmpty.name
String name()
Definition: HM.java:1138
com.cliffc.aa.type.Type.XNIL
static final Type XNIL
Definition: Type.java:333
com.cliffc.aa.HM.HM.T2.find_fidxs
BitsFun find_fidxs()
Definition: HM.java:2100
com.cliffc.aa.HM.HM.T2.dbl_uid
long dbl_uid(T2 t)
Definition: HM.java:1716
com.cliffc.aa.HM.HM.IsEmpty.apply
Type apply(Syntax[] args)
Definition: HM.java:1141
com.cliffc.aa.type.TypeInt.ZERO
static final TypeInt ZERO
Definition: TypeInt.java:49
com.cliffc.aa.util.NonBlockingHashMapLong.put
TypeV put(long key, TypeV val)
Maps the specified key to the specified value in the table.
Definition: NonBlockingHashMapLong.java:278
com.cliffc.aa.HM.HM.Add.Add
Add()
Definition: HM.java:1229
com.cliffc.aa.HM.HM.Add
Definition: HM.java:1227
com.cliffc.aa.HM.HM.Apply.add_val_work
void add_val_work(Syntax child, Worklist work)
Definition: HM.java:693
com.cliffc.aa.HM.HM.VStack._nongen
T2 _nongen
Definition: HM.java:310
com.cliffc.aa.util.Ary.set
E set(int i, E e)
Set existing element.
Definition: Ary.java:133
com.cliffc.aa.HM.HM.Let._arg0
final String _arg0
Definition: HM.java:565
com.cliffc.aa.HM.HM.NotNil.hm
boolean hm(Worklist work)
Definition: HM.java:1161
com.cliffc.aa.util.SB.i
SB i(int d)
Definition: SB.java:38
com.cliffc.aa.HM.HM.Triple.make
PrimSyn make()
Definition: HM.java:1055
com.cliffc.aa.HM.HM.Root.hm
boolean hm(Worklist work)
Definition: HM.java:739
com.cliffc.aa.type.TypeStruct.malloc
static TypeStruct malloc(String name, boolean any, TypeFld[] flds, boolean open)
Definition: TypeStruct.java:175
com.cliffc.aa.type.TypeFld.Access
Definition: TypeFld.java:109
com.cliffc.aa.type.TypeMemPtr.STRPTR
static final TypeMemPtr STRPTR
Definition: TypeMemPtr.java:97
com.cliffc.aa.HM.HM.Ident._init
int _init(Syntax def, T2 idt)
Definition: HM.java:472
com.cliffc.aa.HM.HM.T2.make_nil
static T2 make_nil(T2 leaf)
Definition: HM.java:1322
com.cliffc.aa.HM.HM.T2.meet_alias
BitsAlias meet_alias(T2 that)
Definition: HM.java:1487
com.cliffc.aa.HM.HM.EQ0.EQ0
EQ0()
Definition: HM.java:1123
com.cliffc.aa.type.Bits.meet
B meet(final B bs)
Definition: Bits.java:298
com.cliffc.aa.type.Type.getl
long getl()
Definition: Type.java:802
com.cliffc.aa.HM.HM.T2._union
boolean _union(T2 that, Worklist work)
Definition: HM.java:1578
com.cliffc.aa.HM.HM.VStack.Iter._vstk
VStack _vstk
Definition: HM.java:332
com.cliffc.aa.type.TypeInt.TRUE
static final TypeInt TRUE
Definition: TypeInt.java:44
com.cliffc.aa.HM.HM.If.hm
boolean hm(Worklist work)
Definition: HM.java:1070
com.cliffc.aa.HM.HM.fterm
static Syntax fterm()
Definition: HM.java:231
com.cliffc.aa.HM.HM.Worklist.pop
Syntax pop()
Definition: HM.java:294
com.cliffc.aa.HM.HM.T2.dbl_uid
long dbl_uid(long uid)
Definition: HM.java:1717
com.cliffc.aa.type.TypeStruct._cyclic
boolean _cyclic
Definition: TypeStruct.java:54
com.cliffc.aa.HM.HM.Struct.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:870
com.cliffc.aa.HM.HM.T2.get_dups
VBitSet get_dups(VBitSet dups)
Definition: HM.java:2148
com.cliffc.aa.HM.HM.T2.meet_err
String meet_err(T2 that)
Definition: HM.java:1509
com.cliffc.aa.HM.HM.Field.Field
Field(String id, Syntax str)
Definition: HM.java:893
com
com.cliffc.aa.HM.HM.PrimSyn.p2
SB p2(SB sb, VBitSet dups)
Definition: HM.java:995
com.cliffc.aa.HM.HM.T2.str
SB str(SB sb, VBitSet visit, VBitSet dups)
Definition: HM.java:2163
com.cliffc.aa.HM.HM.reset
static void reset()
Definition: HM.java:143
com.cliffc.aa.HM.HM.Apply.p2
SB p2(SB sb, VBitSet dups)
Definition: HM.java:613
com.cliffc.aa.HM.HM.string
static Syntax string()
Definition: HM.java:263
com.cliffc.aa.HM.HM.Root.Root
Root(Syntax body)
Definition: HM.java:737
com.cliffc.aa.HM.HM.Factor.apply
Type apply(Syntax[] args)
Definition: HM.java:1278
com.cliffc.aa.HM.HM.NotNil.make
PrimSyn make()
Definition: HM.java:1155
com.cliffc.aa.HM.HM.Apply.Apply
Apply(Syntax fun, Syntax... args)
Definition: HM.java:605
com.cliffc.aa.HM.HM.T2.is_fun
boolean is_fun()
Definition: HM.java:1360
com.cliffc.aa.HM.HM.T2.ADUPS
static final NonBlockingHashMapLong< TypeStruct > ADUPS
Definition: HM.java:1426
com.cliffc.aa.type.BitsFun.new_fidx
static int new_fidx(int par)
Definition: BitsFun.java:25
com.cliffc.aa.HM.HM.Con.str
SB str(SB sb)
Definition: HM.java:410
com.cliffc.aa.type.TypeFld.make_from
TypeFld make_from(Type t)
Definition: TypeFld.java:66
com.cliffc.aa.HM.HM.T2._ids
String[] _ids
Definition: HM.java:1313
com.cliffc.aa.HM.HM.EQ
Definition: HM.java:1104
com.cliffc.aa.HM.HM.Con.Con
Con(Type con)
Definition: HM.java:409
com.cliffc.aa.HM.HM.Dec.apply
Type apply(Syntax[] args)
Definition: HM.java:1249
com.cliffc.aa.HM.HM.Apply.T2MAP
static final HashMap< T2, Type > T2MAP
Definition: HM.java:659
com.cliffc.aa.HM.HM.T2.add_deps_work
void add_deps_work(Worklist work)
Definition: HM.java:2132
com.cliffc.aa.type.TypeMemPtr.make_from
TypeMemPtr make_from(TypeObj obj)
Definition: TypeMemPtr.java:73
com.cliffc.aa.type.Type.getstr
String getstr()
Definition: Type.java:806
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.HM.PrimSyn.IDS
static final String[][] IDS
Definition: HM.java:961
com.cliffc.aa.HM.HM.T2.union
boolean union(T2 that, Worklist work)
Definition: HM.java:1527
com.cliffc.aa.HM.HM.Factor.make
PrimSyn make()
Definition: HM.java:1277
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.HM.HM.T2.miss_field
T2 miss_field(String id)
Definition: HM.java:1334
com.cliffc.aa.HM.HM.T2._fidxs
BitsFun _fidxs
Definition: HM.java:1310
com.cliffc.aa.HM.HM.Syntax.toString
final String toString()
Definition: HM.java:390
com.cliffc.aa.HM.HM.T2._uid
final int _uid
Definition: HM.java:1293
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.HM.HM.T2._fresh_unify
boolean _fresh_unify(T2 that, VStack nongen, Worklist work)
Definition: HM.java:1780
com.cliffc.aa.HM.HM.PrimSyn.PAIR_ALIAS
static int PAIR_ALIAS
Definition: HM.java:951
com.cliffc.aa.HM.HM.Let.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:585
com.cliffc.aa.HM.HM.Lambda.hm
boolean hm(Worklist work)
Definition: HM.java:517
com.cliffc.aa.HM.HM.Let._def
final Syntax _def
Definition: HM.java:566
com.cliffc.aa.HM.HM.T2._unify
boolean _unify(T2 that, Worklist work)
Definition: HM.java:1615
com.cliffc.aa.HM.HM.Mul
Definition: HM.java:1207
com.cliffc.aa.HM.HM.T2.debug_find
T2 debug_find()
Definition: HM.java:1364
com.cliffc.aa.type.TypeFlt.FLT64
static final TypeFlt FLT64
Definition: TypeFlt.java:38
com.cliffc.aa.HM.HM.Lambda.add_hm_work
void add_hm_work(Worklist work)
Definition: HM.java:535
com.cliffc.aa.HM.HM.NotNil.prep_tree
int prep_tree(Syntax par, VStack nongen, Worklist work)
Definition: HM.java:1156
com.cliffc.aa.HM.HM.Triple.apply
Type apply(Syntax[] args)
Definition: HM.java:1056
com.cliffc.aa.type.BitsAlias.reset_to_init0
static void reset_to_init0()
Definition: BitsAlias.java:64
com.cliffc.aa.HM.HM.T2._find_fidxs
void _find_fidxs()
Definition: HM.java:2101
com.cliffc.aa.HM.HM.Let._body
final Syntax _body
Definition: HM.java:566
com.cliffc.aa.HM.HM.Pair1.Pair1X.name
String name()
Definition: HM.java:1017
com.cliffc.aa.HM.HM.X
static int X
Definition: HM.java:155
com.cliffc.aa.HM.HM.Dec.Dec
Dec()
Definition: HM.java:1247
com.cliffc.aa.type.TypeMemPtr.make
static TypeMemPtr make(BitsAlias aliases, TypeObj obj)
Definition: TypeMemPtr.java:66