Am Donnerstag, 5. Februar 2004 16:25 schrieb Jens Rieks:
> Am Donnerstag, 5. Februar 2004 14:35 schrieb Leopold Toetsch:
> > Jens Rieks <[EMAIL PROTECTED]> wrote:
> > > Here is a first version of a "Data::Dumper" i've written to be able to
> > > dump the AST of my C parser.
> >
> > Wow, fine.
> >
> > > A dumpertest.imc is included, which shows the dumper in action.
> >
> >   s/included/missing/ :)
>
> dumpertest.imc got stripped, I have resend it.
>
> > > I'am sorry, but I have no idea how to convert this to a test.
> >
> > Test::More provides C<is_deeply> to compare structures.
>
> Hmm, I'll have a look at it later. The C parser has a higher priority atm.
>
> > > ... BTW, is the
> > > order of the hash elements guaranteed to be equal across platforms?
> >
> > Just the opposite, its guaranteed to be not the same even on one
> > platform, albeit a srand() like call is still missing to get really
> > random key order.
> >
> > > .include "../../runtime/parrot/include/datatypes.pasm"
> >
> > That should just be
> >
> >   .include "datatypes.pasm"
> >
> > ... at least, if run from parrot root (which we currently presume)
>
> Oops, fixed. Now it is "runtime/parrot/lib/dumper.imc"
>
> > BTW - we still have the mess with 2 different library directories:
> > - library
> > - runtime/parrot/*
> >
> > We really should clean that up, before more and more code goes in.
> > I'd rather have:
> >
> > - runtime/parrot/lib
> >
> > that is all files that need installation in one place.
>
> Sounds okay. The different include paths we have are a bit messy...

I'am a bit messy, too :-)
Forgot to include the new file. The _init_dumper function is removed, it uses 
the C<errorsoff> from latest CVS to prevent exception raising if the global 
does not exists.

> > leo
>
> jens
=head1 TITLE

dumper.imc - PIR version of Data::Dumper

=head1 VERSION

version 0.02

=head1 SYNOPSIS

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

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

.include "datatypes.pasm"

=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_PerlVal
    _register_dumper( .PerlInt, sub )
    _register_dumper( .PerlNum, sub )

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

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