aa
TypeStruct.java
Go to the documentation of this file.
1 package com.cliffc.aa.type;
2 
3 import com.cliffc.aa.AA;
4 import com.cliffc.aa.util.*;
5 
6 import org.jetbrains.annotations.NotNull;
7 
8 import java.util.*;
9 import java.util.function.Predicate;
10 
11 import static com.cliffc.aa.AA.unimpl;
12 import static com.cliffc.aa.type.TypeFld.Access;
13 import static com.cliffc.aa.type.TypeMemPtr.NO_DISP;
14 
50 public class TypeStruct extends TypeObj<TypeStruct> {
51  private TypeFld[] _flds; // The fields. Effectively final. Public for iteration.
52  public boolean _open; // Fields after _fld.length are treated as ALL (or ANY)
53 
54  public boolean _cyclic; // Type is cyclic. This is a summary property, not a part of the type, hence is not in the equals nor hash
55  private TypeStruct init( String name, boolean any, TypeFld[] flds, boolean open ) {
56  super.init(TSTRUCT, name, any, any);
57  _flds = flds;
58  _open = open;
59  return this;
60  }
61 
62  // Hash code computation.
63  // Fairly subtle, because the typical hash code is built up from the hashes of
64  // its parts, but the parts are not available during construction of a cyclic type.
65  // TODO: If not cyclic, do a proper recursive hash
66  @Override public int compute_hash() {
67  int hash1 = super.compute_hash(), hash = hash1 +(_open?1023:0);
68  assert hash1 != 0;
69  // Compute hash from field names and orders and access.
70  for( TypeFld fld : _flds ) { assert fld._hash!=0; hash = (hash + fld._hash) | (hash >>> 17); }
71  return hash == 0 ? hash1 : hash;
72  }
73 
74  // Returns 1 for definitely equals, 0 for definitely unequals, and -1 if
75  // needing the cyclic test.
76  private int cmp( TypeStruct t ) {
77  if( !super.equals(t) ) return 0;
78  if( _flds.length != t._flds.length || _open != t._open ) return 0;
79  if( _flds == t._flds ) return 1;
80  for( int i=0; i<_flds.length; i++ )
81  if( !Util.eq(_flds[i]._fld,t._flds[i]._fld) || _flds[i]._access!=t._flds[i]._access )
82  return 0;
83  for( int i=0; i<_flds.length; i++ )
84  if( _flds[i]._t!=t._flds[i]._t )
85  return -1; // Some not-pointer-equals child types, must do the full check
86  return 1; // All child types are pointer-equals, so must be equals.
87  }
88 
89  @Override public boolean equals( Object o ) {
90  if( this==o ) return true;
91  if( !(o instanceof TypeStruct) ) return false;
92  TypeStruct t = (TypeStruct)o;
93  // While we would like to use the notion of interned Type[] during the
94  // normal Type.INTERN check, we also get here during building of cyclic
95  // structures for which we'll fall into the cyclic check - as the Type[]s
96  // are not interned yet.
97  int x = cmp(t);
98  if( x != -1 ) return x == 1;
99  // Unlike all other non-cyclic structures which are built bottom-up, cyclic
100  // types have to be built all-at-once, and thus hash-cons and equality-
101  // tested with a cyclic-aware equals check.
102  return cycle_equals(t);
103  }
104 
105  private static final Ary<TypeStruct> CYCLES = new Ary<>(new TypeStruct[0]);
106  private TypeStruct find_other() {
107  int idx = CYCLES.find(this);
108  return idx != -1 ? CYCLES.at(idx^1) : null;
109  }
110  @Override public boolean cycle_equals( Type o ) {
111  if( this==o ) return true;
112  if( !(o instanceof TypeStruct) ) return false;
113  TypeStruct t = (TypeStruct)o;
114  TypeStruct t2 = find_other();
115  if( t2 !=null ) return t2==t ; // Already in cycle report equals or not
116  TypeStruct t3 = t.find_other();
117  if( t3 !=null ) return t3==this;// Already in cycle report equals or not
118  int x = cmp(t);
119  if( x != -1 ) return x == 1;
120 
121  int len = CYCLES._len;
122  CYCLES.add(this).add(t);
123  boolean eq=cycle_equals0(t);
124  assert CYCLES._len==len+2;
125  CYCLES._len=len;
126  return eq;
127  }
128  private boolean cycle_equals0( TypeStruct t ) {
129  for( int i=0; i<_flds.length; i++ ) {
130  Type t0 = _flds[i]._t;
131  Type t1 = t._flds[i]._t;
132  if( t0!=t1 && // Normally suffices to test ptr-equals only
133  (t0==null || t1==null || // Happens when asserting on partially-built cyclic types
134  !t0.cycle_equals(t1)) ) // Must do a full cycle-check
135  return false;
136  }
137  return true;
138  }
139 
140  static boolean isDigit(char c) { return '0' <= c && c <= '9'; }
141  private boolean is_tup() {
142  if( _flds.length<=1 ) return true;
143  return isDigit(_flds[1]._fld.charAt(0));
144  }
145  @Override public SB str( SB sb, VBitSet dups, TypeMem mem, boolean debug ) {
146  if( dups.tset(_uid) ) return sb.p('$'); // Break recursive printing cycle
147  if( _any ) sb.p('~');
148  sb.p(_name);
149  boolean is_tup = is_tup();
150  sb.p(is_tup ? "(" : "@{");
151  // Special shortcut for the all-prims display type
152  if( fld_find("!") != -1 && fld_find("math_pi") != -1 ) {
153  Type t1 = _flds[1]._t;
154  sb.p(t1 instanceof TypeFunPtr
155  ? (((TypeFunPtr)t1)._fidxs.above_center() ? "PRIMS" : "LOW_PRIMS")
156  : "PRIMS_"+t1);
157  } else {
158  boolean field_sep=false;
159  for( int i=0; i<_flds.length; i++ ) {
160  if( !debug && i==0 && Util.eq(_flds[0]._fld,"^") ) continue; // Do not print the ever-present display
161  _flds[i].str(sb,dups,mem,debug); // Field name, access mod, type
162  sb.p(is_tup ? ", " : "; "); // Between fields
163  field_sep=true;
164  }
165  if( _open ) sb.p("..."); // More fields allowed
166  else if( field_sep ) sb.unchar().unchar();
167  }
168  sb.p(!is_tup ? "}" : ")");
169  return sb;
170  }
171 
172  // Unlike other types, TypeStruct might make cyclic types for which a
173  // DAG-like bottom-up-remove-dups approach cannot work.
174  static { new Pool(TSTRUCT,new TypeStruct()); }
175  public static TypeStruct malloc( String name, boolean any, TypeFld[] flds, boolean open ) {
176  return POOLS[TSTRUCT].<TypeStruct>malloc().init(name, any,flds,open);
177  }
180  return hashcons_free();
181  }
182 
183  // Make a collection of fields, with no display and all with default names and final fields.
184  public static TypeFld[] flds(Type t1 ) { return TypeFlds.ts(TypeFld.NO_DISP,TypeFld.make_arg(t1,1)); }
185  public static TypeFld[] flds(Type t1, Type t2 ) { return TypeFlds.ts(TypeFld.NO_DISP,TypeFld.make_arg(t1,1), TypeFld.make_arg(t2,2)); }
186  public static TypeFld[] tups(Type t1, Type t2 ) { return TypeFlds.ts(TypeFld.NO_DISP,TypeFld.make_tup(t1,1), TypeFld.make_tup(t2,2)); }
187  public static TypeFld[] tups(Type t1, Type t2, Type t3) { return TypeFlds.ts(TypeFld.NO_DISP,TypeFld.make_tup(t1,1), TypeFld.make_tup(t2,2), TypeFld.make_tup(t3,3)); }
188 
189  // Make a display field and a specific named field
190  public static TypeStruct make( String fld_name, Type t ) { return make(fld_name,t,Access.Final); }
191  public static TypeStruct make( String fld_name, Type t, Access a ) { return make(TypeFlds.ts(TypeFld.NO_DISP,TypeFld.make(fld_name,t,a,1))); }
192  // Make using the fields, with no struct name, low and closed; typical for a
193  // well-known structure. Make auto-allocate a TypeFld[], if not already
194  // allocated - which is a perf-hit in high usage points. Typically used this
195  // way in tests.
196  public static TypeStruct make( TypeFld... flds ) { return make("",false,flds,false); }
197  // Make auto-allocate a TypeFld[], if not already allocated - which is a
198  // perf-hit in high usage points. Typically used this way in tests.
199  public static TypeStruct make( Type... ts ) {
200  TypeFld[] flds = TypeFlds.get(ts.length+1);
201  flds[0]=TypeFld.NO_DISP;
202  for( int i=0; i<ts.length; i++ )
203  flds[i+1] = TypeFld.make(TypeFld.fldBot,ts[i],i+1);
204  return make("",false,flds,false);
205  }
206  // Malloc/hashcons in one pass
207  public static TypeStruct make( String name, boolean any, TypeFld[] flds, boolean open ) { return malloc(name,any,flds,open).hashcons_freeS(); }
208 
209  // Make an "open" struct with an initial display field.
210  public static TypeStruct open(Type tdisp) { return make("",false,TypeFlds.ts(TypeFld.make_tup(tdisp,0)),true); }
211  // Make a closed struct from an open one
212  public TypeStruct close() { assert _open; return malloc(_name,_any,_flds,false).hashcons_freeS(); } // Mark as no-more-fields
213 
214  // Make a named TypeStruct from an unnamed one
215  public TypeStruct make_from( String name ) { return malloc(name,_any,_flds,_open).hashcons_freeS(); }
216  // Make a TypeStruct with all new fields
219 
220  @Override boolean is_display() {
221  return
222  this==TypeMemPtr.DISPLAY || this==TypeMemPtr.DISPLAY._dual ||
223  (_flds.length >= 1 && _flds[0].is_display_ptr());
224  }
225 
226  // The lattice extreme values
227  public static final TypeStruct ANYSTRUCT = make("",true ,new TypeFld[0],false);
228  public static final TypeStruct ALLSTRUCT = make("",false,new TypeFld[0],true );
229 
230  // A bunch of types for tests
231  public static final TypeStruct POINT = make(flds(TypeFlt.FLT64,TypeFlt.FLT64));
232  public static final TypeStruct NAMEPT= make("Point:",false,POINT._flds,false);
233  static final TypeStruct TFLT64= make(".",TypeFlt.FLT64); // ( flt)
234  public static final TypeStruct A = make("a",TypeFlt.FLT64);
235  private static final TypeStruct C0 = make("c",TypeInt.FALSE); // @{c:0}
236  private static final TypeStruct D1 = make("d",TypeInt.TRUE ); // @{d:1}
237  public static final TypeStruct ARW = make("a",TypeFlt.FLT64,Access.RW);
238  public static final TypeStruct FLT64 = make(flds(TypeFlt.FLT64)); // {flt->flt}
239  public static final TypeStruct INT64_INT64= make(flds(TypeInt.INT64,TypeInt.INT64)); // {int int->int }
240 
241  // Pile of sample structs for testing
243 
244  // Dual the flds, dual the tuple.
245  @Override protected TypeStruct xdual() {
246  TypeFld[] flds = TypeFlds.get(_flds.length);
247  for( int i=0; i<_flds.length; i++ ) flds[i] = _flds[i].dual();
248  return new TypeStruct().init(_name,!_any,TypeFlds.hash_cons(flds),!_open);
249  }
250 
251  // Recursive dual
252  @Override TypeStruct rdual() {
253  if( _dual != null ) return _dual;
254  // Clone the fields for the recursive dual, and grab the field duals
255  TypeFld[] flds = TypeFlds.get(_flds.length);
256  for( int i=0; i<_flds.length; i++ )
257  // Some fields are interned already, the cyclic ones are not.
258  flds[i] = _flds[i].interned() ? _flds[i]._dual : _flds[i].xdual();
259  TypeStruct dual = _dual = new TypeStruct().init(_name,!_any,flds,!_open);
260  if( _hash != 0 ) {
261  assert _hash == compute_hash();
262  dual._hash = dual.compute_hash(); // Compute hash before recursion
263  }
264  for( int i=0; i<_flds.length; i++ )
265  flds[i] = _flds[i].interned() ? _flds[i]._dual : _flds[i].rdual();
266  dual._flds = TypeFlds.hash_cons(flds); // hashcons cyclic arrays
267  dual._dual = this;
268  dual._cyclic = _cyclic;
269  return dual;
270  }
271 
272  // Standard Meet. Types-meet-Types and fld-meet-fld. Fld strings can be
273  // top/bottom for tuples. Structs with fewer fields are virtually extended
274  // with either top or bottom accordingly, to Meet against the other side.
275  // Field names only restrict matches and do not affect the algorithm complexity.
276  //
277  // Types can be in cycles: See Large Comment Above. We effectively unroll
278  // each type infinitely until both sides are cycling and take the GCD of
279  // cycles. Different fields are Meet independently and unroll independently.
280  @Override protected Type xmeet( Type t ) {
281  switch( t._type ) {
282  case TSTRUCT:break;
283  case TARY:
284  case TLIVE:
285  case TSTR: return OBJ;
286  case TOBJ: return t.xmeet(this);
287  case TFUNSIG:
288  case TFLT:
289  case TINT:
290  case TTUPLE :
291  case TFUNPTR:
292  case TMEMPTR:
293  case TRPC:
294  case TMEM: return ALL;
295  default: throw typerr(t); // All else should not happen
296  }
297  TypeStruct thsi = this;
298  TypeStruct that = (TypeStruct)t;
299  // INVARIANT: Both this and that are prior existing & interned.
300  assert RECURSIVE_MEET > 0 || (thsi.interned() && that.interned());
301  // INVARIANT: Both MEETS are empty at the start. Nothing involved in a
302  // potential cycle is interned until the Meet completes.
303  assert RECURSIVE_MEET > 0 || (MEETS0.isEmpty());
304 
305  // If both are cyclic, we have to do the complicated cyclic-aware meet
306  if( _cyclic && that._cyclic )
307  return cyclic_meet(that);
308  // Recursive but not cyclic; since at least one of these types is
309  // non-cyclic normal recursion will bottom-out.
310 
311  // If unequal length; then if short is low it "wins" (result is short) else
312  // short is high and it "loses" (result is long).
313  return thsi._flds.length <= that._flds.length ? thsi.xmeet1(that,false) : that.xmeet1(thsi,false);
314  }
315 
316  // Meet 2 structs, shorter is 'this'.
317  private TypeStruct xmeet1( TypeStruct tmax, boolean is_loop ) {
318  int len = _any ? tmax._flds.length : _flds.length;
319  // Meet of common elements
320  TypeFld[] flds = TypeFlds.get(len);
321  for( int i=0; i<_flds.length; i++ )
322  flds[i] = is_loop && flds[i]._access==Access.Final
323  ? _flds[i] // Ignore RHS on final fields around loops
324  : _flds[i].xmeet(tmax._flds[i]); // Recursive not cyclic
325  // Elements only in the longer tuple; the short struct must be high and so
326  // is effectively infinitely extended with high fields.
327  for( int i=_flds.length; i<len; i++ )
328  flds[i] = tmax._flds[i];
329  // Ignore name in the non-recursive meet, it will be computed by the outer
330  // 'meet' call anyways.
331  return malloc("",_any&tmax._any,flds,_open|tmax._open).hashcons_freeS();
332  }
333 
334  // Recursive meet in progress.
335  // Called during class-init.
336  private static class TPair {
338  private static TPair KEY = new TPair(null,null);
339  static TPair set(TypeStruct ts0, TypeStruct ts1) {KEY._ts0=ts0; KEY._ts1=ts1; return KEY; }
340  TPair(TypeStruct ts0, TypeStruct ts1) { _ts0=ts0; _ts1=ts1; }
341  @Override public int hashCode() { return (_ts0.hashCode()<<17) | _ts1.hashCode(); }
342  @Override public boolean equals(Object o) {
343  return _ts0.equals(((TPair)o)._ts0) && _ts1.equals(((TPair)o)._ts1);
344  }
345  }
346  private static final HashMap<TPair,TypeStruct> MEETS0 = new HashMap<>();
347 
348  // Both structures are cyclic. The meet will be "as if" both structures are
349  // infinitely unrolled, Meeted, and then re-rolled. If cycles are of uneven
350  // length, the end result will be the cyclic GCD length.
352  // Walk 'this' and 'that' and map them both (via MEETS0) to a shared common
353  // Meet result. Only walk the cyclic parts... cyclically. When visiting a
354  // finite-sized part we use the normal recursive Meet. When doing the
355  // cyclic part, we use the normal Meet except we need to use the mapped
356  // Meet types. As part of these Meet operations we can end up Meeting Meet
357  // types with each other more than once, or more than once from each side -
358  // which means already visited Types might need to Meet again, even as they
359  // are embedded in other Types - which leads to the need to use Tarjan U-F
360  // to union Types on the fly.
361 
362  // See if we have worked on this unique pair before. If so, the cycle has
363  // been closed and just return that prior (unfinished) result.
364  TypeStruct mt = MEETS0.get(TPair.set(this,that));
365  if( mt != null ) return mt; // Cycle has been closed
366  mt = this._clone();
367  TypeStruct mx = that;
368  MEETS0.put(new TPair(this,that),mt);
369 
370  // Do a shallow MEET: meet of field names and _any and all things that can
371  // be computed without the cycle. _flds[]._t not filled in yet.
372  int len = mt.len(mx); // Length depends on all the Structs Meet'ing here
373  if( len != mt._flds.length )
374  mt._flds = Arrays.copyOf(mt._flds, len);// escaped a _flds
375  if( mt._any && !mx._any ) mt._any = mt._use = false;
376  if(!mt._open && mx._open) mt._open=true ;
377  for( int i=0; i<len; i++ )
378  mt._flds[i] = TypeFld.cmeet(mt._flds[i],i<mx._flds.length ? mx._flds[i] : null);
379  mt._name = mt.mtname(mx,mt);
380  mt._hash = mt.compute_hash(); // Compute hash now that fields and flags are set
381 
382  // Since the result is cyclic, we cannot test the cyclic parts for
383  // pre-existence until the entire cycle is built. We can't intern the
384  // partially built parts, but we want to use the normal xmeet call - which
385  // normally recursively interns. Turn off interning with the global
386  // RECURSIVE_MEET flag.
387  RECURSIVE_MEET++;
388 
389  // For-all _ts edges do the Meet. Some are not-recursive and mapped, some
390  // are part of the cycle and mapped, some
391  for( int i=0; i<len; i++ ) {
392  Type lfi = i<this._flds.length ? this._flds[i]._t : null;
393  Type rti = i<that._flds.length ? that._flds[i]._t : null;
394  Type mti = (lfi==null) ? rti : (rti==null ? lfi : lfi.meet(rti));
395  Type mtx = mt._flds[i]._t; // Prior value, perhaps updated recursively
396  Type mts = mtx==null ? mti : mtx.meet(mti); // Meet again
397  mt._flds[i].setX(mts); // Finally update
398  }
399  // Check for repeats right now
400  for( TypeStruct ts : MEETS0.values() )
401  if( ts!=mt && ts.equals(mt) )
402  { mt = ts; break; } // Union together
403 
404  // Lower recursive-meet flag. At this point the Meet 'mt' is still
405  // speculative and not interned.
406  if( --RECURSIVE_MEET > 0 )
407  return mt; // And, if not yet done, just exit with it
408 
409  // Remove any final UF before installation.
410  // Do not install until the cycle is complete.
411  RECURSIVE_MEET++;
412  mt = shrink(mt.reachable(),mt);
413  Ary<Type> reaches = mt.reachable(); // Recompute reaches after shrink
414  assert check_uf(reaches);
415  UF.clear();
416  RECURSIVE_MEET--;
417  // This completes 'mt' as the Meet structure.
418  return mt.install_cyclic(reaches);
419  }
420 
421  // Install, cleanup and return
423  // Check for dups. If found, delete entire cycle, and return original.
424  TypeStruct old = (TypeStruct)intern_lookup();
425  // If the cycle already exists, just drop the new Type on the floor and let
426  // GC get it and return the old Type.
427  if( old == null ) { // Not a dup
428  mark_cyclic(get_cyclic(),reachs);
429  assert !_cyclic || repeats_in_cycles()==null;
430  rdual(); // Complete cyclic dual
431  // Insert all members of the cycle into the hashcons. If self-symmetric,
432  // also replace entire cycle with self at each point.
433  if( equals(_dual) ) throw AA.unimpl();
434  walk( t -> {
435  assert t._hash==0 || t._hash==t.compute_hash();
436  if( t.interned() ) return false;
437  if( t.retern() != t._dual ) t._dual.retern();
438  return true;
439  });
440 
441  assert _flds[0]._t.interned();
442  old = this;
443  }
444  MEETS0.clear();
445  return old;
446  }
447 
448  // Test if this is a cyclic value (and should not be interned) with internal
449  // repeats. i.e., not a minimal cycle.
451  assert _cyclic;
452  return repeats_in_cycles(this,new VBitSet());
453  }
455  if( bs.tset(_uid) ) return null;
456  if( this!=head && equals(head) ) return this;
457  for( TypeFld t : _flds ) {
458  TypeStruct ts = t.repeats_in_cycles(head,bs);
459  if( ts!=null ) return ts;
460  }
461  return null;
462  }
463 
464  // Shallow clone, not interned. Fields are also cloned, but not deeper.
465  private TypeStruct _clone() {
466  assert interned();
467  TypeFld[] flds = TypeFlds.clone(_flds); // Shallow field clone
468  TypeStruct t = malloc(_name,_any,flds,_open);
469  t._hash = t.compute_hash();
470  return t;
471  }
472 
473  // This is for a struct that has grown 'too deep', and needs to be
474  // approximated to avoid infinite growth.
476  private static final IHashMap OLD2APX = new IHashMap();
477  public TypeStruct approx( int cutoff, int alias ) {
478  boolean shallow=true;
479  for( TypeFld fld : _flds )
480  if( fld._t._type == TMEMPTR ) { shallow=false; break; }
481  if( shallow ) return this; // Fast cutout for boring structs
482 
483  // Scan the old copy for elements that are too deep.
484  // 'Meet' those into the clone at one layer up.
485  RECURSIVE_MEET++;
486  assert UF.isEmpty();
487  assert OLD2APX.isEmpty();
488  TypeStruct apx = ax_impl_struct( alias, true, cutoff, null, 0, this, this );
489  // Remove any leftover internal duplication
490  apx = shrink(apx.reachable(),apx);
491  RECURSIVE_MEET--;
492  TypeStruct rez = this;
493  if( apx != this ) {
494  Ary<Type> reaches = apx.reachable();
495  assert check_uf(reaches);
496  assert !check_interned(reaches);
497  rez = apx.install_cyclic(reaches);
498  assert this.isa(rez);
499  }
500  UF.clear();
501  OLD2APX.clear();
502  return rez;
503  }
504 
505  // Make a new TypeStruct which is the merge of the original TypeStruct with
506  // the too-deep parts merged into shallower parts.
507  private static TypeStruct ax_impl_struct( int alias, boolean isnews, int cutoff, Ary<TypeStruct> cutoffs, int d, TypeStruct dold, TypeStruct old ) {
508  assert old.interned();
509  // TODO: If past depth, never use OLD, forces maximal cloning for the
510  // last step, as the last step will be MEET with an arbitrary structure.
511  // Use alternative OLD past depth, to keep looping unrelated types
512  // folding up. Otherwise unrelated types might expand endlessly.
513  TypeStruct nt = OLD2APX.get(old);
514  if( nt != null ) return ufind(nt);
515 
516  if( isnews ) { // Depth-increasing struct?
517  if( d==cutoff ) { // Cannot increase depth any more
518  cutoffs.push(old); // Save cutoff point for later MEET
519  return OLD2APX.get(dold); // Return last valid depth - forces cycle
520  } else {
521  assert cutoffs == null; // Approaching max depth, make a place to record cutoffs
522  if( d+1==cutoff ) cutoffs = new Ary<>(TypeStruct.class);
523  }
524  d++; // Increase depth
525  dold = old; // And this is the last TypeStruct seen at this depth
526  }
527  // Clone the old, to make the approximation into
528  TypeStruct nts = (TypeStruct)old.clone();
529  nts._flds = TypeFlds.clone(old._flds);
530  OLD2APX.put(old,nts);
531  for( int i=0; i<old._flds.length; i++ ) // Fill clone with approximation
532  if( old._flds[i]._t._type == TMEMPTR )
533  nts._flds[i].setX(ax_impl_ptr (alias,cutoff,cutoffs,d,dold,(TypeMemPtr)old._flds[i]._t));
534  else if( old._flds[i]._t._type == TFUNPTR )
535  nts._flds[i].setX(ax_impl_fptr(alias,cutoff,cutoffs,d,dold,(TypeFunPtr)old._flds[i]._t));
536  if( isnews && d==cutoff ) {
537  while( !cutoffs.isEmpty() ) { // At depth limit, meet with cutoff to make the approximation
538  Type mt = ax_meet(new BitSetSparse(), nts,cutoffs.pop());
539  assert mt==nts;
540  }
541  }
542  OLD2APX.put(old,null); // Do not keep sharing the "tails"
543  return nts;
544  }
545 
546  private static TypeMemPtr ax_impl_ptr( int alias, int cutoff, Ary<TypeStruct> cutoffs, int d, TypeStruct dold, TypeMemPtr old ) {
547  assert old.interned();
548  // TODO: If past depth, never use OLD, forces maximal cloning for the
549  // last step, as the last step will be MEET with an arbitrary structure.
550  // Use alternative OLD past depth, to keep looping unrelated types
551  // folding up. Otherwise unrelated types might expand endlessly.
552  TypeMemPtr nt = OLD2APX.get(old);
553  if( nt != null ) return ufind(nt);
554 
555  // Walk internal structure, meeting into the approximation
556  TypeMemPtr nmp = (TypeMemPtr)old.clone();
557  OLD2APX.put(old,nmp);
558  if( old._obj instanceof TypeStruct )
559  nmp._obj = ax_impl_struct(alias,nmp._aliases.test(alias),cutoff,cutoffs,d,dold,(TypeStruct)old._obj);
560  else if( old._obj == TypeObj.XOBJ || old._obj==nmp._obj )
561  ; // No change to nmp._obj
562  else if( old._obj == TypeObj.OBJ )
563  nmp._obj = TypeObj.OBJ; // Falls hard
564  else
565  throw com.cliffc.aa.AA.unimpl();
566  OLD2APX.put(old,null); // Do not keep sharing the "tails"
567  return nmp;
568  }
569  private static Type ax_impl_fptr( int alias, int cutoff, Ary<TypeStruct> cutoffs, int d, TypeStruct dold, TypeFunPtr old ) {
570  assert old.interned();
571  // TODO: If past depth, never use OLD, forces maximal cloning for the
572  // last step, as the last step will be MEET with an arbitrary structure.
573  // Use alternative OLD past depth, to keep looping unrelated types
574  // folding up. Otherwise unrelated types might expand endlessly.
575  TypeFunPtr nt = OLD2APX.get(old);
576  if( nt != null ) return ufind(nt);
577  if( old._disp==Type.ANY )
578  return old; // no ufind because its old
579 
580  // Walk internal structure, meeting into the approximation
581  TypeFunPtr nmp = (TypeFunPtr)old.clone();
582  OLD2APX.put(old,nmp);
583  nmp._disp = ax_impl_ptr(alias,cutoff,cutoffs,d,dold,(TypeMemPtr)old._disp);
584  OLD2APX.put(old,null); // Do not keep sharing the "tails"
585  return nmp;
586  }
587 
588  // Update-in-place 'meet' of pre-allocated new types. Walk all the old type
589  // and meet into the corresponding new type. Changes the internal edges of
590  // the new types, so their hash remains undefined.
591  private static Type ax_meet( BitSetSparse bs, Type nt, Type old ) {
592  assert old.interned();
593  if( nt._hash != 0 && nt.interned() ) return nt.meet(old);
594  assert nt._hash==0; // Not definable yet
595  nt = ufind(nt);
596  if( nt == old ) return old;
597  if( bs.tset(nt._uid,old._uid) ) return nt; // Been there, done that
598 
599  // TODO: Make a non-recursive "meet into".
600  // Meet old into nt
601  switch( nt._type ) {
602  case TSCALAR: break; // Nothing to meet
603  case TFUNPTR: {
604  TypeFunPtr nptr = (TypeFunPtr)nt;
605  if( old == Type.NIL || old == Type.XNIL ) return nptr.ax_meet_nil(old);
606  if( old == Type.SCALAR )
607  return union(nt,old); // Result is a scalar, which changes the structure of the new types.
608  if( old == Type.XSCALAR ) break; // Result is the nt unchanged
609  if( !(old instanceof TypeFunPtr) ) throw AA.unimpl(); // Not a xscalar, not a funptr, probably falls to scalar
610  TypeFunPtr optr = (TypeFunPtr)old;
611  nptr._fidxs = nptr._fidxs.meet(optr._fidxs);
612  // While structs normally meet, function args *join*, although the return still meets.
613  nptr._disp = ax_meet(bs,nptr._disp,optr._disp);
614  break;
615  }
616  case TMEMPTR: {
617  TypeMemPtr nptr = (TypeMemPtr)nt;
618  if( old == Type.NIL || old == Type.XNIL ) return nptr.ax_meet_nil(old);
619  if( old == Type.SCALAR )
620  return union(nt,old); // Result is a scalar, which changes the structure of the new types.
621  if( old == Type.XSCALAR || old == Type.ANY ) break; // Result is the nt unchanged
622  if( !(old instanceof TypeMemPtr) ) throw AA.unimpl(); // Not a xscalar, not a memptr, probably falls to scalar
623  TypeMemPtr optr = (TypeMemPtr)old;
624  nptr._aliases = nptr._aliases.meet(optr._aliases);
625  nptr._obj = (TypeObj)ax_meet(bs,nptr._obj,optr._obj);
626  break;
627  }
628  case TSTRUCT:
629  if( old == TypeObj. OBJ || old == TypeObj.ISUSED ) { nt = old; break; }
630  if( old == TypeObj.XOBJ || old == TypeObj.UNUSED ) break; // No changes, take nt as it is
631  if( !(old instanceof TypeStruct) ) throw AA.unimpl();
632  TypeStruct ots = (TypeStruct)old, nts = (TypeStruct)nt;
633  // Compute a new target length. Generally size is unchanged, but will
634  // change if mixing structs.
635  int len = ots.len(nts); // New length
636  if( len != nts._flds.length ) // Grow/shrink as needed
637  nts._flds = Arrays.copyOf(nts._flds, len);
638  int clen = Math.min(len,ots._flds.length);
639  // Meet all the non-recursive parts
640  nts._any &= ots._any ; nts._use = nts._any;
641  nts._open|= ots._open;
642  for( int i=0; i<clen; i++ )
643  nts._flds[i].cmeet(ots._flds[i]);
644  // Now recursively do all common fields
645  for( int i=0; i<clen; i++ )
646  nts._flds[i].setX(ax_meet(bs,nts._flds[i]._t,ots._flds[i]._t));
647  break;
648  default: throw AA.unimpl();
649  }
650  return nt;
651  }
652 
653  // Walk an existing, not-interned, structure. Stop at any interned leaves.
654  // Check for duplicating an interned Type or a UF hit, and use that instead.
655  // Computes the final hash code.
656  private static final IHashMap DUPS = new IHashMap();
657  public static TypeStruct shrink( Ary<Type> reaches, TypeStruct tstart ) {
658  assert DUPS.isEmpty();
659  // Structs never change their hash based on field types. Set their hash first.
660  for( int i=0; i<reaches._len; i++ ) {
661  Type t = reaches.at(i);
662  if( t instanceof TypeStruct || t instanceof TypeFld )
663  t._hash = t.compute_hash();
664  }
665  // TMPs depend on Structs
666  for( int i=0; i<reaches._len; i++ ) {
667  Type t = reaches.at(i);
668  if( t instanceof TypeMemPtr )
669  t._hash = t.compute_hash();
670  }
671  // TFPs depend on TMPS for display
672  for( int i=0; i<reaches._len; i++ ) {
673  Type t = reaches.at(i);
674  if( t instanceof TypeFunPtr )
675  t._hash = t.compute_hash();
676  }
677 
678  // Need back-edges to do this iteratively in 1 pass. This algo just sweeps
679  // until no more progress, but with generic looping instead of recursion.
680  boolean progress = true;
681  while( progress ) {
682  progress = false;
683  DUPS.clear();
684  for( int j=0; j<reaches._len; j++ ) {
685  Type t = reaches.at(j);
686  Type t0 = ufind(t);
687  Type t1 = t0.intern_lookup();
688  if( t1==null ) t1 = DUPS.get(t0);
689  if( t1 != null ) t1 = ufind(t1);
690  if( t1 == t0 ) continue; // This one is already interned
691  if( t1 != null ) { union(t0,t1); progress = true; continue; }
692 
693  switch( t._type ) {
694  case TMEMPTR: // Update TypeMemPtr internal field
695  TypeMemPtr tm = (TypeMemPtr)t0;
696  TypeObj t4 = tm._obj;
697  TypeObj t5 = ufind(t4);
698  if( t4 != t5 ) {
699  tm._obj = t5;
700  progress |= post_mod(tm);
701  if( !t5.interned() ) reaches.push(t5);
702  }
703  break;
704  case TFUNPTR: // Update TypeFunPtr internal field
705  TypeFunPtr tfptr = (TypeFunPtr)t0;
706  Type t6 = tfptr._disp;
707  Type t7 = ufind(t6);
708  if( t6 != t7 ) {
709  tfptr._disp = t7;
710  progress |= post_mod(tfptr);
711  if( !t7.interned() ) reaches.push(t7);
712  }
713  break;
714  case TSTRUCT: // Update all TypeStruct fields
715  TypeStruct ts = (TypeStruct)t0;
716  for( int i=0; i<ts._flds.length; i++ ) {
717  TypeFld tfld = ts._flds[i], tfld2 = ufind(tfld);
718  if( tfld != tfld2 ) {
719  progress = true;
720  ts._flds[i] = tfld2;
721  }
722  }
723  break;
724  case TFLD: // Update all TFlds
725  TypeFld tfld = (TypeFld)t0;
726  Type tft = tfld._t, t2 = ufind(tft);
727  if( tft != t2 ) {
728  progress = true;
729  tfld.setX(t2);
730  }
731  break;
732 
733  default: break;
734  }
735  DUPS.put(t0);
736  }
737  }
738  DUPS.clear();
739  return ufind(tstart);
740  }
741 
742  // Set hash after field mod, and re-install in dups
743  private static boolean post_mod(Type t) {
744  t._hash = t.compute_hash();
745  DUPS.put(t);
746  return true;
747  }
748 
749 
750  @SuppressWarnings("unchecked")
751  private static <T extends Type> T ufind(T t) {
752  T t0 = (T)UF.get(t._uid), tu;
753  if( t0 == null ) return t; // One step, hit end of line
754  // Find end of U-F line
755  while( (tu = (T)UF.get(t0._uid)) != null ) t0=tu;
756  // Set whole line to 1-step end of line
757  while( (tu = (T)UF.get(t ._uid)) != null ) { assert t._uid != t0._uid; UF.put(t._uid,t0); t=tu; }
758  return t0;
759  }
760  private static <T extends Type> T union( T lost, T kept) {
761  if( lost == kept ) return kept;
762  assert lost._hash==0 || !lost.interned();
763  assert UF.get(lost._uid)==null && UF.get(kept._uid)==null;
764  assert lost._uid != kept._uid;
765  UF.put(lost._uid,kept);
766  return kept;
767  }
768 
769  // Walk, looking for prior interned
770  private static boolean check_interned(Ary<Type> reachs) {
771  for( Type t : reachs )
772  if( t.intern_lookup() != null )
773  return true;
774  return false;
775  }
776 
777  // Reachable collection of TypeMemPtr and TypeStruct.
778  // Optionally keep interned Types. List is pre-order.
779  public Ary<Type> reachable() {
780  Ary<Type> work = new Ary<>(new Type[1],0);
781  push(work, this);
782  int idx=0;
783  while( idx < work._len ) {
784  Type t = work.at(idx++);
785  switch( t._type ) {
786  case TMEMPTR: push(work, ((TypeMemPtr)t)._obj ); break;
787  case TFUNPTR: push(work, ((TypeFunPtr)t)._disp); break;
788  case TFLD : push(work, ((TypeFld )t)._t ); break;
789  case TSTRUCT: for( TypeFld tf : ((TypeStruct)t)._flds ) push(work, tf); break;
790  default: break;
791  }
792  }
793  return work;
794  }
795  private void push( Ary<Type> work, Type t ) {
796  int y = t._type;
797  if( (y==TMEMPTR || y==TFUNPTR || y==TSTRUCT || y==TFLD) &&
798  (t._hash == 0 || !t.interned()) && work.find(t)==-1 )
799  work.push(t);
800  }
801 
802  // Walk, looking for not-minimal. Happens during 'approx' which might
803  // require running several rounds of 'replace' to fold everything up.
804  private static boolean check_uf(Ary<Type> reaches) {
805  int err=0;
806  HashMap<Type,Type> ss = new HashMap<>();
807  for( Type t : reaches ) {
808  Type tt;
809  if( ss.get(t) != null || // Found unresolved dup; ts0.equals(ts1) but ts0!=ts1
810  ((tt = t.intern_lookup()) != null && tt != t) ||
811  ufind(t) != t )
812  err++;
813  ss.put(t,t);
814  }
815  return err == 0;
816  }
817 
818  // Get BitSet of not-interned cyclic bits. Almost classic cycle-finding
819  // algorithm; since Structs have labeled out-edges (with field names), we can
820  // have multiple output edges from the same node (struct) to the same
821  // TypeMemPtr. The classic cycle-finders do not work with multi-edges.
822  private BitSet get_cyclic( ) {
823  return get_cyclic(new BitSet(),new VBitSet(),new Ary<>(Type.class),this);
824  }
825  private static BitSet get_cyclic(BitSet bcs, VBitSet bs, Ary<Type> stack, Type t ) {
826  if( t.interned() ) return bcs;
827  if( bs.test(t._uid) ) { // If visiting again... have found a cycle t->....->t
828  // All on the stack are flagged as being part of a cycle
829  int i;
830  i=stack._len-1;
831  while( i >= 0 && stack.at(i)!=t ) i--;
832  if( i== -1 ) return bcs; // Due to multi-edges, we might not find if dupped, so just ignore
833  for( ; i < stack._len; i++ )
834  bcs.set(stack.at(i)._uid);
835  bcs.set(t._uid);
836  return bcs;
837  }
838  stack.push(t); // Push on stack, in case a cycle is found
839  switch( t._type ) {
840  case TMEMPTR: get_cyclic(bcs,bs,stack,((TypeMemPtr)t)._obj ); break;
841  case TFUNPTR: get_cyclic(bcs,bs,stack,((TypeFunPtr)t)._disp); break;
842  case TFLD : get_cyclic(bcs,bs,stack,((TypeFld )t)._t ); break;
843  case TSTRUCT: bs.set(t._uid); for( TypeFld fld : ((TypeStruct)t)._flds ) get_cyclic(bcs,bs,stack,fld); break;
844  }
845  stack.pop(); // Pop, not part of anothers cycle
846  return bcs;
847  }
848  @SuppressWarnings("unchecked")
849  private void mark_cyclic( BitSet bcs, Ary<Type> reaches ) {
850  for( Type t : reaches ) {
851  if( bcs.get(t._uid) ) {
852  assert t.intern_lookup()==null; // Not interned
853  t._dual=null; // Remove any duals, so re-inserted clean
854  if( t instanceof TypeStruct ) {
855  TypeStruct ts = (TypeStruct)t;
856  ts._cyclic = true;
857  ts._flds = TypeFlds.hash_cons(ts._flds); // hashcons cyclic arrays
858  }
859  }
860  }
861  }
862 
863  // If unequal length; then if short is low it "wins" (result is short) else
864  // short is high and it "loses" (result is long).
865  private int len( TypeStruct tt ) { return _flds.length <= tt._flds.length ? len0(tt) : tt.len0(this); }
866  private int len0( TypeStruct tmax ) { return _any ? tmax._flds.length : _flds.length; }
867 
868 
869  // Buid a (recursively) sharpened pointer from memory. Alias sets can be
870  // looked-up directly in a map from BitsAlias to TypeObjs. This is useful
871  // for resolving all the deep pointer structures at a point in the program
872  // (i.e., error checking arguments). Given a TypeMem and a BitsAlias it
873  // returns a TypeObj (and extends the HashMap for future calls). The TypeObj
874  // may contain deep pointers to other deep TypeObjs, including cyclic types.
875  static TypeMemPtr sharpen( TypeMem mem, TypeMemPtr dull ) {
876  assert dull==dull.simple_ptr() && mem.sharp_get(dull)==null;
877 
878  // Pass 1: fill "dull" cache
879  HashMap<BitsAlias,TypeMemPtr> dull_cache = new HashMap<>();
880  _dull(mem,dull,dull_cache);
881 
882  // Pass 2: Stitch together structs with dull pointers to make a possibly cyclic result.
883  TypeMemPtr sharp = _sharp(mem,dull,dull_cache);
884  assert sharp.interned() == dull_cache.isEmpty();
885  // See if we need to cycle-install any cyclic types
886  if( dull_cache.isEmpty() )
887  return sharp;
888  // On exit, cyclic-intern all cyclic things; remove from dull cache.
889  RECURSIVE_MEET++;
890  TypeStruct mt = (TypeStruct)sharp._obj;
891  mt = shrink(mt.reachable(),mt); // No shrinking nor UF expected
892  Ary<Type> reaches = mt.reachable(); // Recompute reaches after shrink
893  assert check_uf(reaches);
894  UF.clear();
895  RECURSIVE_MEET--;
896  mt = mt.install_cyclic(reaches); // But yes cycles
897  sharp = sharp.make_from(mt);
898  return mem.sharput(dull,sharp);
899  }
900 
901  // Pass 1: fill "dull" cache
902  // Check "dull" & "sharp" cache for hit; if so return.
903  // Walk all aliases;
904  // Get obj from mem; it is "dull".
905  // MEET "dull" objs.
906  // If meet is sharp, put in sharp cache & return.
907  // Put dull ptr to dull meet in dull cache.
908  // Walk dull fields; for all dull TMPs, recurse.
909  private static void _dull( TypeMem mem, TypeMemPtr dull, HashMap<BitsAlias,TypeMemPtr> dull_cache ) {
910  // Check caches and return
911  if( mem.sharp_get(dull) != null ) return;
912  if( dull_cache.get(dull._aliases) != null ) return;
913  if( dull==NO_DISP || dull==NO_DISP.dual() ) { mem.sharput(dull,dull); return; }
914  // Walk and meet "dull" fields; all TMPs will point to ISUSED (hence are dull).
915  boolean any = dull._aliases.above_center();
916  Type t = any ? TypeObj.ISUSED : TypeObj.UNUSED;
917  for( int alias : dull._aliases )
918  if( alias != 0 )
919  for( int kid=alias; kid != 0; kid=BitsAlias.next_kid(alias,kid) ) {
920  TypeObj x = mem.at(kid);
921  t = any ? t.join(x) : t.meet(x);
922  }
923  TypeMemPtr dptr = dull.make_from((TypeObj)t);
924  if( _is_sharp(t) ) { // If sharp, install and return
925  mem.sharput(dull,dptr);
926  return;
927  }
928  // Install in dull result in dull cache BEFORE recursing. We might see it
929  // again if cyclic types.
930  dull_cache.put(dull._aliases,dptr);
931  // Visit all dull pointers and recursively collect
932  for( TypeFld fld : ((TypeStruct)t)._flds ) {
933  Type tt = fld._t;
934  if( tt instanceof TypeFunPtr ) tt = ((TypeFunPtr)tt)._disp;
935  if( tt instanceof TypeMemPtr )
936  _dull(mem,(TypeMemPtr)tt,dull_cache);
937  }
938  }
939  // No dull pointers?
940  private static boolean _is_sharp(Type t) {
941  if( !(t instanceof TypeStruct) ) return true;
942  TypeStruct ts = (TypeStruct)t;
943  for( TypeFld fld : ts._flds ) {
944  Type tt = fld._t;
945  assert fld.interned()==tt.interned();
946  if( !tt.interned() || // Not interned internal, then this is not finished
947  (tt instanceof TypeMemPtr && // Or has internal dull pointers
948  ((TypeMemPtr)tt)._obj == TypeObj.ISUSED) )
949  return false;
950  }
951  return true;
952  }
953 
954  // Pass 2: stitch together structs of dull pointers to make a possibly cyclic type.
955  // Check for hit in sharp cache; if so return it.
956  // Get from dull cache; if not interned, flag as cyclic & return it.
957  // Put not-interned dull clone in dull cache.
958  // Walk all fields.
959  // Copy unless TMP; recurse TMP for field.
960  // If not cyclic, all fields already interned; standard intern, put in sharp; remove dull; & return.
961  // If cyclic, then some field is not interned, put on cyclic list?
962  // Return not-interned value.
963  private static @NotNull TypeMemPtr _sharp( TypeMem mem, TypeMemPtr dull, HashMap<BitsAlias,TypeMemPtr> dull_cache ) {
964  TypeMemPtr sharp = mem.sharp_get(dull);
965  if( sharp != null ) return sharp; // Value returned is sharp and interned
966  TypeMemPtr dptr = dull_cache.get(dull._aliases);
967  if( !dptr.interned() ) // Closed a cycle
968  return dptr; // Not-yet-sharp and not interned; return the work-in-progress
969  // Copy, replace dull with not-interned dull clone. Fields are also cloned, not interned.
970  TypeStruct dts2 = ((TypeStruct)dptr._obj)._clone();
971  TypeMemPtr dptr2 = (TypeMemPtr)dptr.clone();
972  dptr2._obj = dts2; dptr2._hash = dptr2.compute_hash();
973  dull_cache.put(dull._aliases,dptr2);
974  // walk all fields, copy unless TMP.
975  for( int i=0; i<dts2._flds.length; i++ ) {
976  TypeFld dts2_fld = dts2._flds[i];
977  Type t = dts2_fld._t;
978  if( t instanceof TypeMemPtr ) // For TMP, recurse on dull pointers.
979  dts2_fld.setX(_sharp(mem,((TypeMemPtr)t),dull_cache));
980  if( t instanceof TypeFunPtr ) {
981  TypeFunPtr tf = (TypeFunPtr) t;
982  if( tf._disp instanceof TypeMemPtr ) { // Need a pointer to sharpen
983  TypeMemPtr dptr3 = _sharp(mem, (TypeMemPtr) tf._disp, dull_cache);
984  dts2_fld.setX(dptr3.interned() // Sharp return?
985  ? tf.make_from(dptr3) // Make sharp TFP field
986  : tf._sharpen_clone(dptr3)); // Make dull TFP field
987  }
988  }
989  if( dts2_fld._t.interned() )
990  dts2._flds[i] = dts2_fld.hashcons_free();
991  }
992  if( !_is_sharp(dts2) ) return dptr2; // Return the work-in-progress
993  // Then copied field types are all sharp and interned.
994  // Intern the fields themselves.
995  for( int i=0; i<dts2._flds.length; i++ )
996  if( !dts2._flds[i]._t.interned() )
997  dts2._flds[i] = dts2._flds[i].hashcons_free();
998  dull_cache.remove(dull._aliases);// Move the entry from dull cache to sharp cache
999  TypeStruct sts = dts2.hashcons_freeS();
1000  return mem.sharput(dull,dull.make_from(sts));
1001  }
1002 
1003  @Override public Type meet_loop(Type t2) {
1004  if( this==t2 ) return this;
1005  if( !(t2 instanceof TypeStruct) ) return meet(t2);
1006  if( _flds.length != ((TypeStruct)t2)._flds.length ) return meet(t2);
1007  return xmeet1((TypeStruct)t2,true);
1008  }
1009 
1010  // ------ Utilities -------
1011 
1012  public TypeFld fld( int idx ) { return _flds[idx]; } // Field by index
1013  public Type at( int idx ) { return _flds[idx]._t; } // Type by index
1014  public Type last() { return _flds[_flds.length-1]._t; }
1015  public int len() { return _flds.length; } // Count of fields
1016  // Read-only iterator; for( TypeFld fld : flds() )...
1017  // Not guarenteed to be in field-order nor name-order.
1018  public TypeFld[] flds() { return _flds; }
1019 
1020  // Extend the current struct with a new named field
1021  public TypeStruct add_fld( String name, Access mutable ) { return add_fld(name,mutable,Type.SCALAR); }
1022  public TypeStruct add_fld( String name, Access mutable, Type tfld ) {
1023  assert name==null || Util.eq(name,TypeFld.fldBot) || fld_find(name)==-1;
1024  assert !_any && _open;
1025  TypeFld[] flds = TypeFlds.copyOf(_flds,_flds.length+1);
1026  flds[_flds.length] = TypeFld.make(name==null ? TypeFld.fldBot : name,tfld,mutable,_flds.length);
1027  return make(_name,_any,flds,true);
1028  }
1029  // Replace type and accessor
1030  public TypeStruct set_fld( int i, Type t, Access ff ) {
1031  TypeFld[] flds = TypeFlds.copyOf(_flds,_flds.length);
1032  flds[i] = TypeFld.make(_flds[i]._fld,t,ff,_flds[i]._order);
1033  return make_from(flds);
1034  }
1035 
1036  // Return the index of the matching field (or nth tuple), or -1 if not found
1037  // or field-num out-of-bounds.
1038  public int fld_find( String fld ) {
1039  assert !Util.eq(fld,TypeFld.fldTop) && !Util.eq(fld,TypeFld.fldBot);
1040  return TypeFld.fld_find(_flds,fld);
1041  }
1042 
1043  // Update (approximately) the current TypeObj. Updates the named field.
1044  @Override public TypeStruct update(Access fin, String fld, Type val) { return update(fin,fld,val,false); }
1045 
1046  private TypeStruct update(Access fin, String fld, Type val, boolean precise) {
1047  int idx = fld_find(fld);
1048  if( idx == -1 ) return this; // Unknown field, assume changes no fields
1049  // Pointers & Memory to a Store can fall during GCP, and go from r/w to r/o
1050  // and the StoreNode output must remain monotonic. This means store
1051  // updates are allowed to proceed even if in-error.
1052  if( fin==Access.Final || fin==Access.ReadOnly ) precise=false;
1053  Type pval = precise ? val : _flds[idx]._t.meet(val);
1054  Access pfin = precise ? fin : _flds[idx]._access.meet(fin);
1055  TypeFld[] flds = TypeFlds.copyOf(_flds,_flds.length);
1056  flds[idx] = TypeFld.make(fld,pval,pfin,idx);
1057  return make(_name,_any,flds,_open);
1058  }
1059 
1060  @Override TypeObj flatten_fields() {
1061  TypeFld[] flds = TypeFlds.get(_flds.length);
1062  for( int i=0; i<_flds.length; i++ )
1063  flds[i] = _flds[i].make_from(Type.SCALAR,Access.bot());
1064  return make_from(flds);
1065  }
1066 
1067  // Used during liveness propagation from Loads.
1068  // Fields not-loaded are not-live.
1069  @Override TypeObj remove_other_flds(String fld, Type live) {
1070  int idx = fld_find(fld);
1071  if( idx == -1 ) return UNUSED; // No such field, so all fields will be XSCALAR so UNUSED instead
1073  for( int i=0; i<_flds.length; i++ ) {
1074  if( i != idx ) flds[i] = flds[i].setX(XSCALAR,Access.bot());
1075  flds[i] = flds[i].hashcons_free();
1076  }
1077  return make_from(flds);
1078  }
1079 
1080  boolean any_modifiable() {
1081  //if( _open ) return true;
1082  //for( byte b : _flags )
1083  // if( is_modifable(fmod(b)) )
1084  // return true;
1085  //return false;
1086  throw unimpl();
1087  }
1088 
1089  // Widen (lose info), to make it suitable as the default function memory.
1090  // All fields are widened to ALL (assuming a future error Store); field flags
1091  // set to bottom; only the field names are kept.
1092  @Override public TypeStruct crush() {
1093  if( _any ) return this; // No crush on high structs
1094  TypeFld[] flds = TypeFlds.get(_flds.length);
1095  // Keep only the display pointer, as it cannot be stomped even with error code
1096  if( _flds.length>0 && _flds[0].is_display_ptr() )
1097  flds[0] = _flds[0].simple_ptr();
1098  for( int i=1; i<_flds.length; i++ ) { // Widen all fields, as-if crushed by errors, even finals.
1099  // Keep the name and field names untouched.
1100  TypeFld fld = _flds[i];
1102  }
1103  // Low input so low output.
1104  return make_from(flds);
1105  }
1106  // Keep field names and orders. Widen all field contents, including finals.
1107  @Override public TypeStruct widen() {
1108  boolean widen=false;
1109  for( TypeFld fld : _flds )
1110  if( fld._t.widen()!=fld._t )
1111  { widen=true; break; }
1112  if( !widen ) return this;
1114  for( int i=0; i<_flds.length; i++ )
1115  flds[i] = flds[i].setX(_flds[i]._t.widen()).hashcons_free();
1116  return make_from(flds);
1117  }
1118 
1119  // True if isBitShape on all bits
1120  @Override public byte isBitShape(Type t) {
1121  if( isa(t) ) return 0; // Can choose compatible format
1122  if( t.isa(this) ) return 0; // TODO: really: test same flds, each fld isBitShape
1123  return 99;
1124  }
1125 
1126  @Override public Type meet_nil(Type nil) { return this; }
1127 
1128  @Override boolean contains( Type t, VBitSet bs ) {
1129  if( bs==null ) bs=new VBitSet();
1130  if( bs.tset(_uid) ) return false;
1131  for( TypeFld fld : _flds ) if( fld._t==t || fld._t.contains(t,bs) ) return true;
1132  return false;
1133  }
1134 
1135  @Override public void walk( Predicate<Type> p ) {
1136  if( p.test(this) )
1137  for( TypeFld fld : _flds ) fld.walk(p);
1138  }
1139 
1140  // Make a Type, replacing all dull pointers from the matching types in mem.
1141  @Override public TypeStruct make_from(Type head, TypeMem mem, VBitSet visit) {
1142  if( visit.tset(_uid) ) return null;
1144  for( int i=0; i<flds.length; i++ )
1145  flds[i] = flds[i].make_from(head,mem,visit);
1146  return make_from(flds);
1147  }
1148 
1149  // Used for assertions
1150  @Override boolean intern_check1() {
1151  for( TypeFld fld : _flds )
1152  if( fld.intern_lookup()==null )
1153  return false;
1154  return true;
1155  }
1156 }
com.cliffc.aa.type.TypeStruct._open
boolean _open
Definition: TypeStruct.java:52
com.cliffc.aa.type.TypeStruct.last
Type last()
Definition: TypeStruct.java:1014
com.cliffc.aa.type.TypeStruct.ax_impl_struct
static TypeStruct ax_impl_struct(int alias, boolean isnews, int cutoff, Ary< TypeStruct > cutoffs, int d, TypeStruct dold, TypeStruct old)
Definition: TypeStruct.java:507
com.cliffc.aa.util.Ary.at
E at(int i)
Definition: Ary.java:25
com.cliffc.aa.type.TypeStruct.ax_impl_ptr
static TypeMemPtr ax_impl_ptr(int alias, int cutoff, Ary< TypeStruct > cutoffs, int d, TypeStruct dold, TypeMemPtr old)
Definition: TypeStruct.java:546
com.cliffc.aa.type.TypeFld.Access.Final
Final
Definition: TypeFld.java:112
com.cliffc.aa.util.BitSetSparse.tset
boolean tset(int b0, int b1)
Definition: BitSetSparse.java:6
com.cliffc.aa.type.TypeStruct.sharpen
static TypeMemPtr sharpen(TypeMem mem, TypeMemPtr dull)
Definition: TypeStruct.java:875
com.cliffc.aa.type.TypeStruct.push
void push(Ary< Type > work, Type t)
Definition: TypeStruct.java:795
com.cliffc.aa.type.TypeMemPtr.NO_DISP
static final Type NO_DISP
Definition: TypeMemPtr.java:80
com.cliffc.aa.type.TypeStruct.check_uf
static boolean check_uf(Ary< Type > reaches)
Definition: TypeStruct.java:804
com.cliffc.aa.type.TypeStruct.len0
int len0(TypeStruct tmax)
Definition: TypeStruct.java:866
com.cliffc.aa.type.TypeFlds.get
TypeFld[] get()
Definition: TypeFlds.java:59
com.cliffc.aa.util.IHashMap.get
public< T > T get(T key)
Definition: IHashMap.java:11
com.cliffc.aa.type.TypeStruct.repeats_in_cycles
TypeStruct repeats_in_cycles()
Definition: TypeStruct.java:450
com.cliffc.aa.type.TypeStruct.make
static TypeStruct make(Type... ts)
Definition: TypeStruct.java:199
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.type.TypeFld.xmeet
TypeFld xmeet(Type tf)
Definition: TypeFld.java:80
com.cliffc.aa.type.TypeMemPtr.compute_hash
int compute_hash()
Definition: TypeMemPtr.java:34
com.cliffc.aa.type.Type.clone
Type clone()
Definition: Type.java:304
com.cliffc.aa.util.Ary.push
E push(E e)
Add element in amortized constant time.
Definition: Ary.java:58
com.cliffc.aa.type.TypeMem.sharp_get
TypeMemPtr sharp_get(TypeMemPtr tmp)
Definition: TypeMem.java:411
com.cliffc.aa.util.Ary.isEmpty
boolean isEmpty()
Definition: Ary.java:20
com.cliffc.aa.type.Type.isa
boolean isa(Type t)
Definition: Type.java:623
com.cliffc.aa.type.TypeFld._order
int _order
Definition: TypeFld.java:18
com.cliffc.aa.type.TypeMem
Memory type; the state of all of memory; memory edges order memory ops.
Definition: TypeMem.java:53
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.TypeObj< TypeStruct >::_any
boolean _any
Definition: TypeObj.java:16
com.cliffc.aa.type.Type.join
Type join(Type t)
Definition: Type.java:619
com.cliffc.aa.type.TypeStruct.is_display
boolean is_display()
Definition: TypeStruct.java:220
com.cliffc.aa.type.Type.interned
boolean interned()
Definition: Type.java:209
com.cliffc.aa.type.Type.SCALAR
static final Type SCALAR
Definition: Type.java:328
com.cliffc
com.cliffc.aa.type.Type._hash
int _hash
Definition: Type.java:97
com.cliffc.aa.type.Type.widen
Type widen()
Definition: Type.java:828
com.cliffc.aa.util.Ary.pop
E pop()
Definition: Ary.java:41
com.cliffc.aa.util.VBitSet.test
boolean test(int idx)
Definition: VBitSet.java:8
com.cliffc.aa.type.TypeStruct.UF
static final NonBlockingHashMapLong< Type > UF
Definition: TypeStruct.java:475
com.cliffc.aa.type.TypeFld
Definition: TypeFld.java:12
com.cliffc.aa.type.Type.XSCALAR
static final Type XSCALAR
Definition: Type.java:329
com.cliffc.aa.type.TypeStruct.ufind
static< T extends Type > T ufind(T t)
Definition: TypeStruct.java:751
com.cliffc.aa.util
Definition: AbstractEntry.java:1
com.cliffc.aa.type.TypeFld.is_display_ptr
boolean is_display_ptr()
Definition: TypeFld.java:190
com.cliffc.aa.type.TypeStruct.make_from
TypeStruct make_from(Type head, TypeMem mem, VBitSet visit)
Definition: TypeStruct.java:1141
com.cliffc.aa.type.TypeInt
Definition: TypeInt.java:9
com.cliffc.aa.type.TypeStruct.ax_meet
static Type ax_meet(BitSetSparse bs, Type nt, Type old)
Definition: TypeStruct.java:591
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.type.TypeFld.xdual
TypeFld xdual()
Definition: TypeFld.java:69
com.cliffc.aa.type.TypeStruct.isBitShape
byte isBitShape(Type t)
Definition: TypeStruct.java:1120
com.cliffc.aa.type.TypeFlt
Definition: TypeFlt.java:9
com.cliffc.aa.type.TypeStruct.crush
TypeStruct crush()
Definition: TypeStruct.java:1092
com.cliffc.aa.type.TypeStruct.ALLSTRUCT
static final TypeStruct ALLSTRUCT
Definition: TypeStruct.java:228
com.cliffc.aa.util.Ary
Definition: Ary.java:11
com.cliffc.aa.type.Type.compute_hash
int compute_hash()
Definition: Type.java:109
com.cliffc.aa.util.IHashMap
Definition: IHashMap.java:7
com.cliffc.aa.type.BitsAlias
Definition: BitsAlias.java:8
com.cliffc.aa.type.TypeStruct.POINT
static final TypeStruct POINT
Definition: TypeStruct.java:231
com.cliffc.aa.type.TypeStruct.TFLT64
static final TypeStruct TFLT64
Definition: TypeStruct.java:233
com.cliffc.aa.type.Type._type
byte _type
Definition: Type.java:98
com.cliffc.aa.type.TypeFld.Access.RW
RW
Definition: TypeFld.java:111
com.cliffc.aa.type.TypeStruct.A
static final TypeStruct A
Definition: TypeStruct.java:234
com.cliffc.aa.type.TypeStruct.TPair._ts0
TypeStruct _ts0
Definition: TypeStruct.java:337
com.cliffc.aa.type.TypeFld.NO_DISP
static final TypeFld NO_DISP
Definition: TypeFld.java:170
com.cliffc.aa.type.TypeFlds.copyOf
static TypeFld[] copyOf(TypeFld[] flds, int len)
Definition: TypeFlds.java:124
com.cliffc.aa.util.Ary._len
int _len
Definition: Ary.java:13
com.cliffc.aa.type.TypeStruct.cycle_equals
boolean cycle_equals(Type o)
Definition: TypeStruct.java:110
com.cliffc.aa.type.TypeFld.cmeet
static TypeFld cmeet(TypeFld f0, TypeFld f1)
Definition: TypeFld.java:93
com.cliffc.aa.type.TypeStruct.flatten_fields
TypeObj flatten_fields()
Definition: TypeStruct.java:1060
com.cliffc.aa.type.TypeFunPtr._fidxs
BitsFun _fidxs
Definition: TypeFunPtr.java:26
com.cliffc.aa.type.TypeStruct.any_modifiable
boolean any_modifiable()
Definition: TypeStruct.java:1080
com.cliffc.aa.type.TypeStruct.rdual
TypeStruct rdual()
Definition: TypeStruct.java:252
com.cliffc.aa.type.TypeStruct.make_from
TypeStruct make_from(TypeFld[] flds)
Definition: TypeStruct.java:217
com.cliffc.aa.type.TypeFlds
Definition: TypeFlds.java:8
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.type.Type.meet
final Type meet(Type t)
Definition: Type.java:412
com.cliffc.aa.type.TypeStruct.hashcons_freeS
TypeStruct hashcons_freeS()
Definition: TypeStruct.java:178
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.TypeStruct.flds
TypeFld[] flds()
Definition: TypeStruct.java:1018
com.cliffc.aa.type.Bits.test
static boolean test(long[] bits, int i)
Definition: Bits.java:224
com.cliffc.aa.util.BitSetSparse
Definition: BitSetSparse.java:4
com.cliffc.aa.type.TypeMemPtr._obj
TypeObj _obj
Definition: TypeMemPtr.java:26
com.cliffc.aa.type.TypeStruct.at
Type at(int idx)
Definition: TypeStruct.java:1013
com.cliffc.aa.type.TypeStruct.len
int len()
Definition: TypeStruct.java:1015
com.cliffc.aa.type.TypeStruct.str
SB str(SB sb, VBitSet dups, TypeMem mem, boolean debug)
Definition: TypeStruct.java:145
com.cliffc.aa.util.SB.unchar
SB unchar()
Definition: SB.java:58
com.cliffc.aa.type.Type.ALL
static final Type ALL
Definition: Type.java:324
com.cliffc.aa.type.TypeFld.rdual
TypeFld rdual()
Definition: TypeFld.java:70
com.cliffc.aa.type.Type.cycle_equals
boolean cycle_equals(Type t)
Definition: Type.java:118
com.cliffc.aa.type.TypeStruct.TPair.equals
boolean equals(Object o)
Definition: TypeStruct.java:342
com.cliffc.aa.type.TypeStruct.widen
TypeStruct widen()
Definition: TypeStruct.java:1107
com.cliffc.aa.util.VBitSet.tset
boolean tset(int idx)
Definition: VBitSet.java:7
com.cliffc.aa.type.BitsAlias.next_kid
static int next_kid(int alias, int kid)
Definition: BitsAlias.java:66
com.cliffc.aa.type.TypeStruct.INT64_INT64
static final TypeStruct INT64_INT64
Definition: TypeStruct.java:239
com.cliffc.aa.type.Bits.above_center
boolean above_center()
Definition: Bits.java:204
com.cliffc.aa.type.TypeInt.INT64
static final TypeInt INT64
Definition: TypeInt.java:39
com.cliffc.aa.type.TypeStruct._is_sharp
static boolean _is_sharp(Type t)
Definition: TypeStruct.java:940
com.cliffc.aa.type.TypeObj< TypeStruct >::OBJ
static final TypeObj OBJ
Definition: TypeObj.java:44
com.cliffc.aa.type.TypeObj
Definition: TypeObj.java:15
com.cliffc.aa.type.TypeFld.fldBot
static final String fldBot
Definition: TypeFld.java:140
com.cliffc.aa.type.TypeFld.setX
TypeFld setX(Type t)
Definition: TypeFld.java:173
com.cliffc.aa.type.TypeStruct.TPair.KEY
static TPair KEY
Definition: TypeStruct.java:338
com.cliffc.aa.type.TypeStruct.remove_other_flds
TypeObj remove_other_flds(String fld, Type live)
Definition: TypeStruct.java:1069
com.cliffc.aa.type.TypeFld._access
Access _access
Definition: TypeFld.java:17
com.cliffc.aa.util.IHashMap.isEmpty
boolean isEmpty()
Definition: IHashMap.java:14
com.cliffc.aa.type.TypeStruct.OLD2APX
static final IHashMap OLD2APX
Definition: TypeStruct.java:476
com.cliffc.aa.type.Type._dual
T _dual
Definition: Type.java:100
com.cliffc.aa.type.TypeStruct.equals
boolean equals(Object o)
Definition: TypeStruct.java:89
com.cliffc.aa.type.TypeMemPtr.DISPLAY
static final TypeStruct DISPLAY
Definition: TypeMemPtr.java:78
com.cliffc.aa.type.TypeObj.XOBJ
static final TypeObj XOBJ
Definition: TypeObj.java:47
com.cliffc.aa.type.TypeFunPtr._disp
Type _disp
Definition: TypeFunPtr.java:28
com.cliffc.aa.type.TypeStruct.repeats_in_cycles
TypeStruct repeats_in_cycles(TypeStruct head, VBitSet bs)
Definition: TypeStruct.java:454
com.cliffc.aa.type.Type.contains
final boolean contains(Type t)
Definition: Type.java:926
com.cliffc.aa.type.TypeStruct.init
TypeStruct init(String name, boolean any, TypeFld[] flds, boolean open)
Definition: TypeStruct.java:55
com.cliffc.aa.util.Util
Definition: Util.java:5
com.cliffc.aa.type.TypeObj.UNUSED
static final TypeObj UNUSED
Definition: TypeObj.java:46
com.cliffc.aa.type.TypeStruct.post_mod
static boolean post_mod(Type t)
Definition: TypeStruct.java:743
com.cliffc.aa.type.TypeStruct._sharp
static TypeMemPtr _sharp(TypeMem mem, TypeMemPtr dull, HashMap< BitsAlias, TypeMemPtr > dull_cache)
Definition: TypeStruct.java:963
com.cliffc.aa.type.TypeStruct.isDigit
static boolean isDigit(char c)
Definition: TypeStruct.java:140
com.cliffc.aa.type.Type.xmeet
Type xmeet(Type t)
Definition: Type.java:461
com.cliffc.aa.type.TypeObj.ISUSED
static final TypeObj ISUSED
Definition: TypeObj.java:45
com.cliffc.aa.type.TypeFld._fld
String _fld
Definition: TypeFld.java:15
com.cliffc.aa.type.TypeFld.fldTop
static final String fldTop
Definition: TypeFld.java:139
com.cliffc.aa.type.TypeStruct._clone
TypeStruct _clone()
Definition: TypeStruct.java:465
com.cliffc.aa.type.TypeStruct.reachable
Ary< Type > reachable()
Definition: TypeStruct.java:779
com.cliffc.aa.type.TypeStruct.flds
static TypeFld[] flds(Type t1, Type t2)
Definition: TypeStruct.java:185
com.cliffc.aa.type.TypeStruct.DUPS
static final IHashMap DUPS
Definition: TypeStruct.java:656
com.cliffc.aa.type.TypeStruct.open
static TypeStruct open(Type tdisp)
Definition: TypeStruct.java:210
com.cliffc.aa.type.TypeStruct.flds
static TypeFld[] flds(Type t1)
Definition: TypeStruct.java:184
com.cliffc.aa.type.TypeStruct.contains
boolean contains(Type t, VBitSet bs)
Definition: TypeStruct.java:1128
com.cliffc.aa.type.TypeStruct.xmeet
Type xmeet(Type t)
Definition: TypeStruct.java:280
com.cliffc.aa.type.TypeStruct.ARW
static final TypeStruct ARW
Definition: TypeStruct.java:237
com.cliffc.aa.util.VBitSet
Definition: VBitSet.java:5
com.cliffc.aa.type.TypeStruct.TPair.TPair
TPair(TypeStruct ts0, TypeStruct ts1)
Definition: TypeStruct.java:340
com.cliffc.aa.type.TypeStruct.tups
static TypeFld[] tups(Type t1, Type t2)
Definition: TypeStruct.java:186
com.cliffc.aa.type.TypeFunPtr._sharpen_clone
TypeFunPtr _sharpen_clone(TypeMemPtr disp)
Definition: TypeFunPtr.java:191
com.cliffc.aa.type.TypeStruct.make
static TypeStruct make(String name, boolean any, TypeFld[] flds, boolean open)
Definition: TypeStruct.java:207
NotNull
com.cliffc.aa.type.Type.hashcons_free
final T hashcons_free()
Definition: Type.java:153
com.cliffc.aa.util.SB
Tight/tiny StringBuilder wrapper.
Definition: SB.java:8
com.cliffc.aa.type.Type.NIL
static final Type NIL
Definition: Type.java:332
com.cliffc.aa.type.TypeStruct.FLT64
static final TypeStruct FLT64
Definition: TypeStruct.java:238
com.cliffc.aa.type.TypeStruct.walk
void walk(Predicate< Type > p)
Definition: TypeStruct.java:1135
com.cliffc.aa.type.TypeStruct.is_tup
boolean is_tup()
Definition: TypeStruct.java:141
com.cliffc.aa.type.TypeStruct.ax_impl_fptr
static Type ax_impl_fptr(int alias, int cutoff, Ary< TypeStruct > cutoffs, int d, TypeStruct dold, TypeFunPtr old)
Definition: TypeStruct.java:569
com.cliffc.aa.type.TypeFld.walk
void walk(Predicate< Type > p)
Definition: TypeFld.java:194
com.cliffc.aa.type.TypeMemPtr.simple_ptr
Type simple_ptr()
Definition: TypeMemPtr.java:160
com.cliffc.aa.type.TypeStruct.update
TypeStruct update(Access fin, String fld, Type val, boolean precise)
Definition: TypeStruct.java:1046
com.cliffc.aa.AA
an implementation of language AA
Definition: AA.java:9
com.cliffc.aa.type.TypeStruct.D1
static final TypeStruct D1
Definition: TypeStruct.java:236
com.cliffc.aa.type.TypeStruct.len
int len(TypeStruct tt)
Definition: TypeStruct.java:865
com.cliffc.aa.type.TypeStruct.approx
TypeStruct approx(int cutoff, int alias)
Definition: TypeStruct.java:477
com.cliffc.aa.type.TypeStruct.intern_check1
boolean intern_check1()
Definition: TypeStruct.java:1150
com.cliffc.aa.type.TypeStruct.fld_find
int fld_find(String fld)
Definition: TypeStruct.java:1038
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.type.TypeFld.Access.ReadOnly
ReadOnly
Definition: TypeFld.java:110
com.cliffc.aa.type.TypeStruct.fld
TypeFld fld(int idx)
Definition: TypeStruct.java:1012
com.cliffc.aa.type.TypeStruct.set_fld
TypeStruct set_fld(int i, Type t, Access ff)
Definition: TypeStruct.java:1030
com.cliffc.aa.type.TypeStruct.TPair
Definition: TypeStruct.java:336
com.cliffc.aa.type.Type._uid
int _uid
Definition: Type.java:96
com.cliffc.aa.type.TypeFlds.clone
static TypeFld[] clone(TypeFld[] ts)
Definition: TypeFlds.java:116
com.cliffc.aa.type.TypeStruct._flds
TypeFld[] _flds
Definition: TypeStruct.java:51
com.cliffc.aa.type.TypeStruct.make_from
TypeStruct make_from(String name)
Definition: TypeStruct.java:215
com.cliffc.aa.type.TypeStruct.add_fld
TypeStruct add_fld(String name, Access mutable, Type tfld)
Definition: TypeStruct.java:1022
com.cliffc.aa.type.TypeStruct.cycle_equals0
boolean cycle_equals0(TypeStruct t)
Definition: TypeStruct.java:128
com.cliffc.aa.type.TypeStruct.C0
static final TypeStruct C0
Definition: TypeStruct.java:235
com.cliffc.aa.type.TypeStruct.check_interned
static boolean check_interned(Ary< Type > reachs)
Definition: TypeStruct.java:770
com.cliffc.aa.type.TypeStruct.make
static TypeStruct make(String fld_name, Type t, Access a)
Definition: TypeStruct.java:191
com.cliffc.aa.type.TypeStruct.xmeet1
TypeStruct xmeet1(TypeStruct tmax, boolean is_loop)
Definition: TypeStruct.java:317
com.cliffc.aa.type.TypeStruct.TYPES
static final TypeStruct[] TYPES
Definition: TypeStruct.java:242
com.cliffc.aa.util.SB.p
SB p(String s)
Definition: SB.java:13
com.cliffc.aa.type.TypeMemPtr._aliases
BitsAlias _aliases
Definition: TypeMemPtr.java:16
com.cliffc.aa.type.TypeStruct.make_from_flds
TypeStruct make_from_flds(TypeStruct ts)
Definition: TypeStruct.java:218
com.cliffc.aa.type.TypeInt.FALSE
static final Type FALSE
Definition: TypeInt.java:45
com.cliffc.aa.type.TypeFld.simple_ptr
TypeFld simple_ptr()
Definition: TypeFld.java:192
com.cliffc.aa.type.TypeStruct.get_cyclic
BitSet get_cyclic()
Definition: TypeStruct.java:822
com.cliffc.aa.type.TypeStruct.mark_cyclic
void mark_cyclic(BitSet bcs, Ary< Type > reaches)
Definition: TypeStruct.java:849
com.cliffc.aa.type.TypeFld.Access.meet
Access meet(Access a)
Definition: TypeFld.java:130
com.cliffc.aa.type.TypeStruct.add_fld
TypeStruct add_fld(String name, Access mutable)
Definition: TypeStruct.java:1021
com.cliffc.aa.type.Type.dual
final T dual()
Definition: Type.java:361
com.cliffc.aa.type.TypeFld._t
Type _t
Definition: TypeFld.java:16
com.cliffc.aa.type.TypeFlds.hash_cons
static TypeFld[] hash_cons(TypeFld[] ts)
Definition: TypeFlds.java:81
com.cliffc.aa.type.TypeMem.sharput
TypeMemPtr sharput(TypeMemPtr dull, TypeMemPtr sharp)
Definition: TypeMem.java:412
com.cliffc.aa.type.TypeStruct.make
static TypeStruct make(String fld_name, Type t)
Definition: TypeStruct.java:190
com.cliffc.aa.util.NonBlockingHashMapLong
A lock-free alternate implementation of java.util.concurrent.ConcurrentHashMap with primitive long ke...
Definition: NonBlockingHashMapLong.java:91
com.cliffc.aa.type.TypeStruct.shrink
static TypeStruct shrink(Ary< Type > reaches, TypeStruct tstart)
Definition: TypeStruct.java:657
com.cliffc.aa.type.TypeFunPtr.ax_meet_nil
Type ax_meet_nil(Type nil)
Definition: TypeFunPtr.java:167
com.cliffc.aa.type.Type.XNIL
static final Type XNIL
Definition: Type.java:333
com.cliffc.aa.type.TypeStruct.TPair.hashCode
int hashCode()
Definition: TypeStruct.java:341
com.cliffc.aa.type.TypeStruct.malloc
static TypeStruct malloc(String name, boolean any, TypeFld[] flds, boolean open)
Definition: TypeStruct.java:175
com.cliffc.aa.util.Ary.find
int find(E e)
Find the first matching element using ==, or -1 if none.
Definition: Ary.java:192
com.cliffc.aa.type.TypeFld.Access
Definition: TypeFld.java:109
com.cliffc.aa.type.Type.intern_lookup
Type intern_lookup()
Definition: Type.java:210
com.cliffc.aa.type.TypeObj._use
boolean _use
Definition: TypeObj.java:17
com.cliffc.aa.type.TypeStruct.meet_nil
Type meet_nil(Type nil)
Definition: TypeStruct.java:1126
com.cliffc.aa.type.TypeMemPtr.ax_meet_nil
Type ax_meet_nil(Type nil)
Definition: TypeMemPtr.java:203
com.cliffc.aa.type.Bits.meet
B meet(final B bs)
Definition: Bits.java:298
com.cliffc.aa.type.TypeStruct.find_other
TypeStruct find_other()
Definition: TypeStruct.java:106
com.cliffc.aa.type.TypeInt.TRUE
static final TypeInt TRUE
Definition: TypeInt.java:44
com.cliffc.aa.type.TypeStruct.NAMEPT
static final TypeStruct NAMEPT
Definition: TypeStruct.java:232
com.cliffc.aa.type.TypeFld.str
SB str(SB sb, VBitSet dups, TypeMem mem, boolean debug)
Definition: TypeFld.java:44
com.cliffc.aa.type.TypeStruct.get_cyclic
static BitSet get_cyclic(BitSet bcs, VBitSet bs, Ary< Type > stack, Type t)
Definition: TypeStruct.java:825
com.cliffc.aa.type.TypeStruct._cyclic
boolean _cyclic
Definition: TypeStruct.java:54
com.cliffc.aa.type.TypeStruct.xdual
TypeStruct xdual()
Definition: TypeStruct.java:245
com.cliffc.aa.type.TypeStruct.cyclic_meet
TypeStruct cyclic_meet(TypeStruct that)
Definition: TypeStruct.java:351
com.cliffc.aa.type.TypeStruct.meet_loop
Type meet_loop(Type t2)
Definition: TypeStruct.java:1003
com.cliffc.aa.type.TypeFld.make_arg
static TypeFld make_arg(Type t, int order)
Definition: TypeFld.java:64
com
com.cliffc.aa.type.TypeStruct.ANYSTRUCT
static final TypeStruct ANYSTRUCT
Definition: TypeStruct.java:227
com.cliffc.aa.type.TypeFld.Access.bot
static Access bot()
Definition: TypeFld.java:118
com.cliffc.aa.type.TypeFld.fld_find
static int fld_find(TypeFld[] flds, String fld)
Definition: TypeFld.java:197
com.cliffc.aa.util.IHashMap.put
public< T > T put(T kv)
Definition: IHashMap.java:9
com.cliffc.aa.type.TypeStruct.TPair._ts1
TypeStruct _ts1
Definition: TypeStruct.java:337
com.cliffc.aa.type.TypeFlds.ts
static TypeFld[] ts(TypeFld t0)
Definition: TypeFlds.java:82
com.cliffc.aa.type.TypeMem.at
TypeObj at(int alias)
Definition: TypeMem.java:135
com.cliffc.aa.type.TypeStruct._dull
static void _dull(TypeMem mem, TypeMemPtr dull, HashMap< BitsAlias, TypeMemPtr > dull_cache)
Definition: TypeStruct.java:909
com.cliffc.aa.util.IHashMap.clear
void clear()
Definition: IHashMap.java:13
com.cliffc.aa.type.TypeMemPtr.make_from
TypeMemPtr make_from(TypeObj obj)
Definition: TypeMemPtr.java:73
com.cliffc.aa.type.TypeStruct.cmp
int cmp(TypeStruct t)
Definition: TypeStruct.java:76
com.cliffc.aa.type.TypeStruct.tups
static TypeFld[] tups(Type t1, Type t2, Type t3)
Definition: TypeStruct.java:187
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.type.TypeStruct.close
TypeStruct close()
Definition: TypeStruct.java:212
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.type.TypeStruct.CYCLES
static final Ary< TypeStruct > CYCLES
Definition: TypeStruct.java:105
com.cliffc.aa.type.TypeFlt.FLT64
static final TypeFlt FLT64
Definition: TypeFlt.java:38
com.cliffc.aa.type.TypeStruct.make
static TypeStruct make(TypeFld... flds)
Definition: TypeStruct.java:196
com.cliffc.aa.type.TypeStruct.update
TypeStruct update(Access fin, String fld, Type val)
Definition: TypeStruct.java:1044
com.cliffc.aa.type.TypeFunPtr.make_from
TypeFunPtr make_from(TypeMemPtr disp)
Definition: TypeFunPtr.java:75
com.cliffc.aa.type.TypeStruct.MEETS0
static final HashMap< TPair, TypeStruct > MEETS0
Definition: TypeStruct.java:346
com.cliffc.aa.type.TypeStruct.TPair.set
static TPair set(TypeStruct ts0, TypeStruct ts1)
Definition: TypeStruct.java:339