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