#!/usr/bin/perl package Blondie::Backend::Perl::Interpreter; use base qw/Blondie::Reducer Blondie::Reducer::DynamicScoping/; use strict; use warnings; no warnings 'recursion'; sub new { my $class = shift; bless { params => undef, param_stack => [], }, $class; } sub execute { my $self = shift; my $prog = shift; $self->reduce($prog); } sub can_reduce { 1 } sub generic_reduce { my $self = shift; my $node = shift; die "generic reductions don't make sense while interpreting ($node)"; } sub reduce_val { $_[1]->val } sub reduce_app { my $self = shift; my $app = shift; my ($thunk, @params) = map { $self->reduce($_) } $app->values; $self->prepare_scope(@params); # profiling actually slows this down by around 30% #my $t = times; #my $v = $self->reduce($thunk); #my $t2 = times; #$self->{prof}{$thunk} += $t2-$t; #$v; } sub reduce_thunk { my $self = shift; my $thunk = shift; # FIXME - in the future the compiler might allow adding globals # ought to check if the runtime has a hash for this right now this is a non # issue since even higher order functions get prims instead of thunks when # possible my $body = $thunk->val; $self->enter_scope; my $v = $self->reduce($body); $self->leave_scope; return $v; } sub reduce_param { my $self = shift; my $param = shift; $self->new_pad($param->val => $self->shift_param); } sub reduce_prim { my $self = shift; my $prim = shift; $self->enter_scope; my @params = $self->params; # the body is a code ref my $v = $prim->body->($self, map { $self->shift_param } 1 .. $prim->arity); $self->leave_scope; return $v; } sub reduce_sym { my $self = shift; my $symbol = shift->val; $self->find_dyn_sym($symbol)->val; } sub reduce_seq { my $self = shift; my $seq = shift; (map { $self->reduce($_) } $seq->values)[-1]; } sub leave_scope { my $self = shift; $self->SUPER::leave_scope(@_); # warn "unbound params @{ $self->{params} }" if $self->{params} and @{ $self->{params} }; $self->{params} = pop @{ $self->{param_stack} }; } sub prepare_scope { my $self = shift; push @{ $self->{param_stack} }, $self->{params}; $self->{params} = [ @_ ]; } sub shift_param { my $self = shift; shift @{ $self->{params} }; } sub params { my $self = shift; @{ $self->{params} }; } __PACKAGE__; __END__ =pod =head1 NAME Blondie::Backend::Perl::Interpreter - A perl interpreter for compiled Blondie programs. =head1 SYNOPSIS use Blondie::Backend::Perl::Interpreter; =head1 DESCRIPTION This is a subclass of L that performs the actions denoted by the AST, ultimately flattenning the tree down to a single value. =cut