Here is the latest version of the _dumper() function.
A test file is attached to my the next mail.

Changes:
- PerlHash keys are now sorted
  (It makes it possible to write more simple tests.)
- no init method call is needed anymore

Just .include "library/dumper.imc" at the end of you program, and use 
_dumper( "name", pmc ) whereever you want ;-)

jens
=head1 TITLE

dumper.imc - PIR version of Data::Dumper

=head1 VERSION

version 0.04

=head1 SYNOPSIS

        ...     
        
        # dump the P0 register
        _dumper( "P0", P0 )
        
        ...
        
        END
        .include "library/dumper.imc"

=head1 DESCRIPTION
    
    PIR implementation of Perl's Data::Dumper module.
    
=cut

.include "datatypes.pasm"
.include "library/sort.imc"

=head1 FUNCTIONS

This library provides the following functions:

=over 4

=item _helper()

For internal use only. Initializes an array with helper callbacks.

This function returns the helper array.

=cut

.sub _helper
    saveall
    .local pmc helper
    .local pmc sub
    .local int type
    
    errorsoff 1 # .PARROT_ERRORS_GLOBALS_FLAG
    helper = global "Data::Dumper::helper"
    typeof type, helper
    if type == .PerlArray goto END

    new helper, .PerlArray
    global "Data::Dumper::helper" = helper

    newsub sub, .Sub, _dump_PerlArray
    _register_dumper( .PerlArray, sub )

    newsub sub, .Sub, _dump_PerlHash
    _register_dumper( .PerlHash, sub )

    newsub sub, .Sub, _dump_PerlString
    _register_dumper( .PerlString, sub )

    newsub sub, .Sub, _dump_PerlVal
    _register_dumper( .PerlInt, sub )
    _register_dumper( .PerlNum, sub )

    newsub sub, .Sub, _dump_PerlUndef
    _register_dumper( .PerlUndef, sub )

    newsub sub, .Sub, _dump_Sub
    _register_dumper( .Sub, sub )

END:
    restoreall
    .pcc_begin_return
    .return helper
    .pcc_end_return
.end

=item _register_dumper( id, sub )

Registers a dumper for new PMC type.

=over 4

=item id

the PMC id, as returned by the C<typeof> op.

=item sub

a Sub pmc, that gets called in order to dump the content of the given PMC

=back

For example:

        newsub sub, .Sub, _dump_PerlArray
        _register_dumper( .PerlArray, sub )

This function returns nothing.

=cut
        
.sub _register_dumper
    .param int id
    .param pmc sub
    .local pmc helper

    helper = global "Data::Dumper::helper"
    set helper[id], sub
    
    .pcc_begin_return
    .pcc_end_return
.end

=item _dumper( name, pmc[, indent] )

This is the public interface to the dumper library.

=over 4

=item name

Required. The name of the PMC.

=item pmc

Required. The PMC to dump.

=item indent

Optional. The indent used at the start of each line printed.

=back

B<Note:> This function currently returns nothing. It should return
the dumped data as a string, like Perl's Data::Dumper. Instead,
everything is printed out using C<print>.

B<Note: #2> PerlHash keys are now sorted using C<_sort()> (library/sort.imc)

=cut

.sub _dumper
    .param string name
    .param pmc dump
    .param string indent

    _helper()    
    _do_dumper_named( name, dump, indent )
    print "\n"
    
    .pcc_begin_return
    .pcc_end_return
.end

#
# internal helper function
#
.sub _do_dumper_named
    .param string name
    .param pmc dump
    .param string indent

    print indent
    print "\""
    print name
    print "\" => "
    
    _do_dumper_unnamed( dump, indent )
    
    .pcc_begin_return
    .pcc_end_return
.end

#
# internal helper function
#
.sub _do_dumper_unnamed
    .param pmc dump
    .param string indent
    .local pmc helper
    .local int type
    .local int exist
    .local pmc cb

    helper = global "Data::Dumper::helper"

    typeof type, dump
    exists exist, helper[type]
    if exist, CALL_HELPER

    print "unkown-type(pmc #"
    print type
    print ")"    
    branch DONE
        
CALL_HELPER:

    cb = helper[type]
    
    saveall
    set S5, indent
    set P6, dump
    invokecc cb    
    restoreall
    
DONE:
    .pcc_begin_return
    .pcc_end_return
.end

#
# Dumps a PerlArray pmc
#
.sub _dump_PerlArray
    .param pmc array
    .param string indent
    .local string subindent
    .local int size
    .local int pos
    .local pmc val
    .local string posstr
    .local int tmp
    
    subindent = "    "
    concat subindent, indent
    
    print "PerlArray (size:"
    print array
    print ") ["

    set size, array
    set pos, 0

    unless size, iter_end
    
iter_loop:
    print "\n"
    
    set val, array[pos]
    
    print subindent
    _do_dumper_unnamed( val, subindent )
    
    # next array member
    inc pos
    
    # skip the ',' after the last element
    if pos >= size goto iter_end
    
    print ","

    # elements left?
    branch iter_loop    

iter_end:
    print "\n"
    print indent
    print "]"

    .pcc_begin_return
    .pcc_end_return
.end

#
# Dumps a PerlHash pmc
#
.sub _dump_PerlHash
    .param pmc hash
    .param string indent
    .local string subindent
    .local pmc iter
    .local string key
    .local pmc val
    .local pmc keys
    
    subindent = "    "
    concat subindent, indent
    
    print "PerlHash {"

    new keys, .PerlArray
    new iter, .Iterator, hash
    set iter, 0

iter_loop:
    unless iter, iter_end

    shift key, iter
    push keys, key
    branch iter_loop
    
iter_end:
    _sort( keys )
    
dump_loop:
    unless keys, dump_end
    
    print "\n"
    
    shift key, keys
    set val, hash[key]
    _do_dumper_named( key, val, subindent )
    
    print ","
        
    branch dump_loop

dump_end:
    print "\n"
    print indent
    print "}"

    .pcc_begin_return
    .pcc_end_return
.end

#
# Dumps a PerlString pmc
#
.sub _dump_PerlString
    .param pmc str
    .param string indent
    
    print "\""
    print str
    print "\""
    
    .pcc_begin_return
    .pcc_end_return
.end

#
# Dumps a Perl[Num,Int] pmc
#
.sub _dump_PerlVal
    .param pmc val
    .param string indent
    
    print val
    
    .pcc_begin_return
    .pcc_end_return
.end

#
# Dumps a PerlUndef pmc
#
.sub _dump_PerlUndef
    .param pmc val
    .param string indent
    
    print "undef"
    
    .pcc_begin_return
    .pcc_end_return
.end

#
# Dumps a Sub pmc
#
.sub _dump_Sub
    .param pmc val
    .param string indent
    
    print "sub { ... }"
    
    .pcc_begin_return
    .pcc_end_return
.end

=head1 AUTHOR

Jens Rieks E<lt>parrot at jensbeimsurfen dot deE<gt> is the author
and maintainer.
Please send patches and suggestions to the Perl 6 Internals mailing list.

=head1 COPYRIGHT

Copyright (c) 2004, the Perl Foundation.

=cut

Reply via email to