Here is a first version of a "Data::Dumper" i've written to be able to dump 
the AST of my C parser.

A dumpertest.imc is included, which shows the dumper in action.
I'am sorry, but I have no idea how to convert this to a test. BTW, is the 
order of the hash elements guaranteed to be equal across platforms?

jens
=head1 TITLE

dumper.imc - PIR version of Data::Dumper

=head1 SYNOPSIS
        
        ...
        
        # not needed anymore in the near future
        _init_dumper()
        
        ...
        
        # dump the P0 register
        _dumper( "P0", P0 )
        
        ...
        
        END
        .include "library/dumper.imc"

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

.include "../../runtime/parrot/include/datatypes.pasm"

=head1 FUNCTIONS

This library provides the following functions:

=over 4

=item _init_dumper()

For internal use only. Initializes a hash with helper callbacks.
At the moment, this function has to be called before any use of C<_dumper()>.
This will change in the near future.

This function returns nothing.

=cut

.sub _init_dumper
    saveall
    .local pmc helper
    .local pmc sub
    
    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_PerlVal
    _register_dumper( .PerlInt, sub )
    _register_dumper( .PerlNum, sub )

    newsub sub, .Sub, _dump_PerlString
    _register_dumper( .PerlString, sub )
    
    restoreall
    .pcc_begin_return
    .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>.

=cut

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

    _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 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 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

    subindent = "    "
    concat subindent, indent
    
    print "PerlHash {"

    new iter, .Iterator, hash
    set iter, 0

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

iter_end:
    print "\n"
    print indent
    print "}"

    .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