#!/usr/bin/perl
package Blondie::Reducer;
use strict;
use warnings;
use UNIVERSAL::moniker;
use Scalar::Util ();
sub reduce {
my $self = shift;
my $node = shift;
return $node unless $self->can_reduce($node);
if (Scalar::Util::blessed($node) && (my $meth = $self->can("reduce_" . $node->moniker))) {
return $self->$meth($node);
} else {
return $self->generic_reduce($node);
}
}
sub can_reduce {
my $self = shift;
my $node = shift;;
return unless Scalar::Util::blessed($node);
return if $node->atomic;
return 1;
}
sub generic_reduce {
my $self = shift;
my $node = shift;
return $node unless Scalar::Util::blessed($node);
$node->isa("Blondie::Node")
or die "it doesn't look like $node is a piece of a Blondie program.";
$node->fmap(sub { $self->reduce($_[0]) });
}
__PACKAGE__;
__END__
=pod
=head1 NAME
Blondie::Reducer - generic reducing base class for fmapping nodes.
=head1 SYNOPSIS
package My::ASTWalker;
use base qw/Blondie::Reducer/;
sub reduce_sym {
my $self = shift;
my $sym_node = shift;
my $symbol = $sym_node->val;
$table{$symbol}; # find the symbol
}
# and then
my $reduced = My::ASTWalker->new->reduce($program);
=head1 DESCRIPTION
=cut