Hi all,

again, here is a new patch for libraray/dumper.pmc.
It implements:
- support for self-referential data structures
- support for PMC NULL values
- print no comma after the last entry of a hash
- 3 new tests covering the new functionality
- some minor internal tweaks
- initial support for OrderedHash, ManagedStruct, UnManagedStruct
  (How can I dump them? The iterator PMC is not working with them.)

Next planned things:
- support for OrderedHash, ManagedStruct, UnManagedStruct
- "compressed" output of larger arrays with many equal values,
   or maybe several values per line
But they have no high priority at the moment, if anyone wants/needs one of 
these (or another) feature, just mail me :-)

jens
Index: library/dumper.imc
===================================================================
RCS file: /cvs/public/parrot/library/dumper.imc,v
retrieving revision 1.3
diff -u -w -r1.3 dumper.imc
--- library/dumper.imc	17 Feb 2004 07:23:24 -0000	1.3
+++ library/dumper.imc	17 Feb 2004 21:20:46 -0000
@@ -4,7 +4,7 @@
 
 =head1 VERSION
 
-version 0.04
+version 0.07
 
 =head1 SYNOPSIS
 
@@ -55,6 +55,9 @@
     new helper, .PerlArray
     global "Data::Dumper::helper" = helper
 
+    newsub sub, .Sub, _dump_null
+    _register_dumper( 0, sub )
+
     newsub sub, .Sub, _dump_PerlArray
     _register_dumper( .PerlArray, sub )
 
@@ -74,6 +77,15 @@
     newsub sub, .Sub, _dump_Sub
     _register_dumper( .Sub, sub )
 
+    newsub sub, .Sub, _dump_OrderedHash
+    _register_dumper( .OrderedHash, sub )
+
+    newsub sub, .Sub, _dump_ManagedStruct
+    _register_dumper( .ManagedStruct, sub )
+
+    newsub sub, .Sub, _dump_UnManagedStruct
+    _register_dumper( .UnManagedStruct, sub )
+
 END:
     restoreall
     .pcc_begin_return
@@ -150,6 +162,7 @@
     .param string name
     .param pmc dump
     .param string indent
+    .local pmc cache
 
     # check the number of INT args
     if I1 != 0 goto ERROR
@@ -158,29 +171,24 @@
     # check the number of STR args
     if I2 > 2 goto ERROR
     if I2 < 0 goto ERROR
-    if I2 == 2 goto NAMED
-    if I2 == 0 goto UNNAMED
     
-    # I2 == 1; no ident specified
+    if I2 == 2 goto NAMED
+    # I2 <= 1; no indent specified
     set indent, ""
+    if I2 == 1 goto NAMED
+    # I2 == 0; no indent and no name
+    # use a default name
+    set name, "VAR1"
     
 NAMED:
     _helper()    
-    _do_dumper_named( name, dump, indent )
+    new cache, .PerlArray
+    _do_dumper_showname( name, name, dump, cache, indent )
     print "\n"
     .pcc_begin_return
     .return 1
     .pcc_end_return
 
-UNNAMED:
-    _helper()
-    _do_dumper_unnamed( dump, "" )
-    print "\n"
-    
-    .pcc_begin_return
-    .return 1
-    .pcc_end_return
-    
 ERROR:
     print "_dumper Syntax:\n"
     print "_dumper( pmc )\n"
@@ -192,38 +200,114 @@
 .end
 
 #
+# caches the already printed PMCs and their names
+#
+.sub _dumper_cache
+    .param pmc cache
+    .param pmc find
+    .param string defname
+    .local int i
+    .local pmc entry
+    .local string name
+    .local pmc pname
+    
+    set i, cache
+LOOP:
+    dec i
+    dec i
+    if i < 0 goto NOTFOUND
+    entry = cache[i]
+    ne_addr entry, find, LOOP
+
+    # found entry => get its name
+    inc i
+    name = cache[i]
+    dec i
+    .pcc_begin_return
+    .return i
+    .return name
+    .pcc_end_return
+
+NOTFOUND:
+    set name, defname
+    push cache, find
+    push cache, name
+    .pcc_begin_return
+    .return -1
+    .return name
+    .pcc_end_return
+.end
+
+#
 # internal helper function
 #
-.sub _do_dumper_named
+.sub _do_dumper_showname
+    .param string shortname
     .param string name
     .param pmc dump
+    .param pmc cache
     .param string indent
 
     print indent
     print "\""
-    print name
+    print shortname
     print "\" => "
     
-    _do_dumper_unnamed( dump, indent )
-    
-    .pcc_begin_return
-    .pcc_end_return
+    # use tail calling instead of
+    # _do_dumper( name, dump, cache, indent )
+    newsub P0, .Sub, _do_dumper
+    set S5, name
+    set P5, dump
+    set P6, cache
+    set S6, indent
+    set I0, 1
+    set I1, 0
+    set I2, 2
+    set I3, 2
+    set I4, 0
+    invoke
 .end
 
 #
 # internal helper function
 #
-.sub _do_dumper_unnamed
+.sub _do_dumper
+    .param string name
     .param pmc dump
+    .param pmc cache
     .param string indent
     .local pmc helper
     .local int type
     .local int exist
     .local pmc cb
+    .local string name2
+    .local pmc ret
+    
+    ret = P1
+    newsub helper, .Sub, _dumper_cache
+    .pcc_begin prototyped
+    .arg cache
+    .arg dump
+    .arg name
+    .pcc_call helper
+    .result type
+    .result name
+    .pcc_end
+
+    if type == -1 goto NOT_IN_CACHE
+    # name found in cache:
+    print "\\"
+    print name
+    branch END
 
+NOT_IN_CACHE:
+    # get the global helper hash
     helper = global "Data::Dumper::helper"
 
+    set type, 0
+    isnull dump, ISNULL
     typeof type, dump
+ISNULL:
     exists exist, helper[type]
     if exist, CALL_HELPER
 
@@ -233,21 +317,26 @@
     branch DONE
         
 CALL_HELPER:
-
     cb = helper[type]
-    
-    saveall
-    set S5, indent
-    set P6, dump
-    invokecc cb    
-    restoreall
+    .pcc_begin prototyped
+    .arg name
+    .arg indent
+    .arg dump
+    .arg cache
+    .pcc_call cb
+    .pcc_end
     
 DONE:
+    isnull dump, END
     prophash cb, dump
     unless cb goto END
 
     print " with-properties: "
-    _dump_Hash( cb, indent )
+    clone name2, name
+    concat name2, ".properties()"
+    
+    # XXX: use tail calling
+     _do_dumper( name2, cb, cache, indent )
     
 END:
     .pcc_begin_return
@@ -258,13 +347,15 @@
 # Dumps a PerlArray pmc
 #
 .sub _dump_PerlArray
+    .param string name
     .param pmc array
+    .param pmc cache
     .param string indent
     .local string subindent
     .local int size
     .local int pos
     .local pmc val
-    .local string posstr
+    .local string name2
     .local int tmp
     
     subindent = "    "
@@ -282,10 +373,16 @@
 iter_loop:
     print "\n"
     
+    print subindent
+    
+    new val, .PerlArray
+    push val, name
+    push val, pos
+    sprintf name2, "%s[%d]", val
+    
     set val, array[pos]
     
-    print subindent
-    _do_dumper_unnamed( val, subindent )
+    _do_dumper( name2, val, cache, subindent )
     
     # next array member
     inc pos
@@ -311,26 +408,42 @@
 # Dumps a PerlHash pmc
 #
 .sub _dump_PerlHash
+    .param string name
     .param pmc hash
+    .param pmc cache
     .param string indent
     
     print "PerlHash "
-    _dump_Hash( hash, indent )
-    .pcc_begin_return
-    .pcc_end_return
+
+    # use tail calling instead of
+    # _dump_Hash( name, hash, cache, indent )
+    newsub P0, .Sub, _dump_Hash
+    set S5, name
+    set P5, hash
+    set P6, cache
+    set S6, indent
+    set I0, 1
+    set I1, 0
+    set I2, 2
+    set I3, 2
+    set I4, 0
+    invoke
 .end
 
 #
 # Dumps a 'generic' Hash
 #
 .sub _dump_Hash
+    .param string name
     .param pmc hash
+    .param pmc cache
     .param string indent
     .local string subindent
     .local pmc iter
     .local string key
     .local pmc val
     .local pmc keys
+    .local string name2
     
     subindent = "    "
     concat subindent, indent
@@ -357,9 +470,17 @@
     print "\n"
     
     shift key, keys
+    
+    new val, .PerlArray
+    push val, name
+    push val, key
+    sprintf name2, "%s[\"%s\"]", val
+
     set val, hash[key]
-    _do_dumper_named( key, val, subindent )
     
+    _do_dumper_showname( key, name2, val, cache, subindent )
+    
+    unless keys, dump_end
     print ","
         
     branch dump_loop
@@ -377,7 +498,9 @@
 # Dumps a PerlString pmc
 #
 .sub _dump_PerlString
+    .param string name
     .param pmc str
+    .param pmc cache
     .param string indent
     
     print "\""
@@ -392,7 +515,9 @@
 # Dumps a Perl[Num,Int] pmc
 #
 .sub _dump_PerlVal
+    .param string name
     .param pmc val
+    .param pmc cache
     .param string indent
     
     print val
@@ -405,7 +530,9 @@
 # Dumps a PerlUndef pmc
 #
 .sub _dump_PerlUndef
+    .param string name
     .param pmc val
+    .param pmc cache
     .param string indent
     
     print "undef"
@@ -418,11 +545,70 @@
 # Dumps a Sub pmc
 #
 .sub _dump_Sub
+    .param string name
     .param pmc val
+    .param pmc cache
     .param string indent
     
     print "sub { ... }"
     
+    .pcc_begin_return
+    .pcc_end_return
+.end
+
+#
+# Dumps a null pmc
+#
+.sub _dump_null
+    .param string name
+    .param pmc val
+    .param pmc cache
+    .param string indent
+    
+    print "null"
+    
+    .pcc_begin_return
+    .pcc_end_return
+.end
+
+#
+# Dumps a OrderedHash pmc
+#
+.sub _dump_OrderedHash
+    .param string name
+    .param pmc hash
+    .param pmc cache
+    .param string indent
+
+    print "OrderedHash { ... }"
+    .pcc_begin_return
+    .pcc_end_return
+.end
+
+#
+# Dumps a ManagedStruct pmc
+#
+.sub _dump_ManagedStruct
+    .param string name
+    .param pmc hash
+    .param pmc cache
+    .param string indent
+
+    print "ManagedStruct { ... }"
+    .pcc_begin_return
+    .pcc_end_return
+.end
+
+#
+# Dumps a UnManagedStruct pmc
+#
+.sub _dump_UnManagedStruct
+    .param string name
+    .param pmc hash
+    .param pmc cache
+    .param string indent
+
+    print "UnManagedStruct { ... }"
     .pcc_begin_return
     .pcc_end_return
 .end
Index: t/pmc/dumper.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/dumper.t,v
retrieving revision 1.2
diff -u -w -r1.2 dumper.t
--- t/pmc/dumper.t	17 Feb 2004 07:23:26 -0000	1.2
+++ t/pmc/dumper.t	17 Feb 2004 21:20:47 -0000
@@ -1,8 +1,9 @@
 #! perl -w
 use strict;
 
-use Parrot::Test tests => 8;
+use Parrot::Test tests => 11;
 
+# no. 1
 output_is(<<'CODE', <<'OUT', "dumping array of sorted numbers");
 ##PIR##
 .sub _main
@@ -39,6 +40,7 @@
 ]
 OUT
 
+# no. 2
 output_is(<<'CODE', <<'OUT', "dumping unsorted numbers");
 ##PIR##
 .sub _main
@@ -75,6 +77,7 @@
 ]
 OUT
 
+# no. 3
 output_is(<<'CODE', <<'OUT', "dumping sorted strings");
 ##PIR##
 .sub _main
@@ -107,6 +110,7 @@
 ]
 OUT
 
+# no. 4
 output_is(<<'CODE', <<'OUT', "sorting unsorted strings");
 ##PIR##
 .sub _main
@@ -139,6 +143,7 @@
 ]
 OUT
 
+# no. 5
 output_is(<<'CODE', <<'OUT', "dumping different types");
 ##PIR##
 .sub _main
@@ -195,6 +200,7 @@
 ]
 OUT
 
+# no. 6
 output_is(<<'CODE', <<'OUT', "dumping complex data");
 ##PIR##
 .sub _main
@@ -260,24 +266,24 @@
 "hash1" => PerlHash {
 }
 "hash1" => PerlHash {
-    "hello" => "world",
+    "hello" => "world"
 }
 "hash1" => PerlHash {
     "hello" => "world",
-    "hello2" => "world2",
+    "hello2" => "world2"
 }
 "hash1" => PerlHash {
     "hash2" => PerlHash {
     },
     "hello" => "world",
-    "hello2" => "world2",
+    "hello2" => "world2"
 }
 "hash1" => PerlHash {
     "hash2" => PerlHash {
-        "hello3" => "world3",
+        "hello3" => "world3"
     },
     "hello" => "world",
-    "hello2" => "world2",
+    "hello2" => "world2"
 }
 "hash1" => PerlHash {
     "hash2" => PerlHash {
@@ -288,16 +294,17 @@
             "test",
             PerlHash {
                 "is" => "cool",
-                "name" => "parrot",
+                "name" => "parrot"
             }
         ],
-        "hello3" => "world3",
+        "hello3" => "world3"
     },
     "hello" => "world",
-    "hello2" => "world2",
+    "hello2" => "world2"
 }
 OUT
 
+# no.7
 output_is(<<'CODE', <<'OUT', "properties");
 ##PIR##
 .sub _main
@@ -322,15 +329,16 @@
 .end
 .include "library/dumper.imc"
 CODE
-PerlArray (size:2) [
+"VAR1" => PerlArray (size:2) [
     "test1",
     "test2"
-] with-properties: {
+] with-properties: PerlHash {
     "key1" => "value1",
-    "key2" => "value2",
+    "key2" => "value2"
 }
 OUT
 
+# no. 8
 output_is(<<'CODE', <<'OUT', "indent string");
 ##PIR##
 .sub _main
@@ -375,13 +383,11 @@
                 |"test"
             |]
         |],
-        |"test2" => "test2",
+        |"test2" => "test2"
     |},
-    |"test1" => "test1",
-|} with-properties: {
-    |"array2" => PerlArray (size:1) [
-        |"test"
-    |],
+    |"test1" => "test1"
+|} with-properties: PerlHash {
+    |"array2" => \hash["hash2"]["array"][1]
 |}
 |"hash" => PerlHash {
     |"hash2" => PerlHash {
@@ -391,14 +397,102 @@
                 |"test"
             |]
         |],
-        |"test2" => "test2",
+        |"test2" => "test2"
     |},
-    |"test1" => "test1",
-|} with-properties: {
-    |"array2" => PerlArray (size:1) [
-        |"test"
-    |],
+    |"test1" => "test1"
+|} with-properties: PerlHash {
+    |"array2" => \hash["hash2"]["array"][1]
 |}
 name = 'hash'
 indent = '|'
+OUT
+
+# no. 9
+output_is(<<'CODE', <<'OUT', "back-referencing properties");
+##PIR##
+.sub _main
+    .local pmc hash
+    
+    new hash, .PerlHash
+    
+    set hash["hello"], "world"
+    setprop hash, "backref", hash
+    _dumper( hash )
+    end
+.end
+.include "library/dumper.imc"
+CODE
+"VAR1" => PerlHash {
+    "hello" => "world"
+} with-properties: PerlHash {
+    "backref" => \VAR1
+}
+OUT
+
+# no. 10
+output_is(<<'CODE', <<'OUT', "self-referential properties");
+##PIR##
+.sub _main
+    .local pmc hash
+    .local pmc prop
+    
+    new hash, .PerlHash
+    
+    set hash["hello"], "world"
+    prophash prop, hash
+    setprop hash, "self", prop
+    _dumper( hash )
+    end
+.end
+.include "library/dumper.imc"
+CODE
+"VAR1" => PerlHash {
+    "hello" => "world"
+} with-properties: PerlHash {
+    "self" => \VAR1.properties()
+}
+OUT
+
+# no. 11
+output_is(<<'CODE', <<'OUT', "self-referential properties");
+##PIR##
+.sub _main
+    .local pmc array
+    .local pmc hash1
+    .local pmc hash2
+    .local pmc prop
+    
+    new array, .PerlArray
+    new hash1, .PerlHash
+    new hash2, .PerlHash
+    
+    set hash1["hello1"], "world1"
+    set hash2["hello2"], "world2"
+    prophash prop, hash1
+    set prop["das leben"], "ist schoen"
+    setprop hash2, "hash1prop", prop
+    push array, hash1
+    push array, hash2
+    push array, prop
+    prophash prop, hash2
+    push array, prop
+    _dumper( array )
+    end
+.end
+.include "library/dumper.imc"
+CODE
+"VAR1" => PerlArray (size:4) [
+    PerlHash {
+        "hello1" => "world1"
+    } with-properties: PerlHash {
+        "das leben" => "ist schoen"
+    },
+    PerlHash {
+        "hello2" => "world2"
+    } with-properties: PerlHash {
+        "hash1prop" => \VAR1[0].properties()
+    },
+    \VAR1[0].properties(),
+    \VAR1[1].properties()
+]
 OUT

Reply via email to