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