| 396 | // VISIT endlessly for some minor speed hope |
| 397 | static String prettyPrint( Type t, Object x ) { return _print(t,x,new SB(), new IdentityHashMap<>()).toString(); } |
| 398 | static SB _print( Type t, Object x, SB sb, IdentityHashMap<Object,Object> visit ) { |
| 399 | if( x instanceof String s ) return sb.p(s); |
| 400 | if( x == null ) return sb.p("null"); |
| 401 | return switch( t ) { |
| 402 | case TypeInteger i -> sb.p( (Long)x); |
| 403 | case TypeFloat f -> sb.p((Double)x); |
| 404 | case TypeMemPtr tmp -> { |
| 405 | if( visit.containsKey(x) ) yield sb.p("$cyclic"); |
| 406 | visit.put(x,x); |
| 407 | // Since never can close the type cycle, without cyclic types, have |
| 408 | // to handle FRefs even here |
| 409 | if( tmp.isFRef() ) |
| 410 | tmp = tmp.makeFrom(((TypeMemPtr)Parser.TYPES.get(tmp._obj._name))._obj); |
| 411 | |
| 412 | Object[] xs = (Object[])x; // Array of fields |
| 413 | if( tmp._obj.isAry() ) { |
| 414 | Type elem = tmp._obj._fields[1]._type; |
| 415 | if( elem == TypeInteger.U8 ) { |
| 416 | // Shortcut u8[] as a String |
| 417 | for( Object o : xs ) |
| 418 | sb.p((char)(long)(Long)o); |
| 419 | } else { |
| 420 | // Array of elements |
| 421 | elem.print(sb).p("[ "); |
| 422 | for( Object o : xs ) |
| 423 | _print( elem, o, sb, visit ).p( "," ); |
| 424 | sb.unchar().p("]"); |
| 425 | } |
| 426 | } else { |
| 427 | sb.p(tmp._obj._name).p("{"); |
| 428 | Field[] flds = tmp._obj._fields; |
| 429 | for( int i=0; i<flds.length; i++ ) |
| 430 | _print( flds[i]._type,xs[i], sb.p(flds[i]._fname).p("="), visit ).p(","); |
| 431 | sb.unchar().p("}"); |
| 432 | } |
| 433 | yield sb; |
| 434 | } |
| 435 | case TypeFunPtr tfp -> sb.p(x.toString()); |
| 436 | case TypeRPC rpc -> sb.p(x.toString()); |
| 437 | case TypeMem mem -> sb.p("$mem"); |
| 438 | case TypeTuple tt -> { |
| 439 | if( tt._types.length>1 && tt._types[1] instanceof TypeMemPtr ) |
| 440 | // Assume a NewNode |
| 441 | yield _print( tt._types[1], x, sb, visit ); |
| 442 | throw Utils.TODO(); |
| 443 | } |
| 444 | case Type tt -> { |
| 445 | if( tt == Type.NIL ) yield sb.p("null"); |
| 446 | throw Utils.TODO(); |
| 447 | } |
| 448 | }; |
| 449 | } |
| 450 | } |