[Bps-public-commit] r19340 - in Lorzy/trunk: lib/Lorzy/Expression t
clkao at bestpractical.com
clkao at bestpractical.com
Fri Apr 24 03:55:57 EDT 2009
Author: clkao
Date: Fri Apr 24 03:55:57 2009
New Revision: 19340
Added:
Lorzy/trunk/lib/Lorzy/Expression/Break.pm
Lorzy/trunk/lib/Lorzy/Expression/Continue.pm
Lorzy/trunk/t/loop-control.t
Modified:
Lorzy/trunk/lib/Lorzy/Exception.pm
Lorzy/trunk/lib/Lorzy/Expression/ForEach.pm
Log:
loop exceptions for breaking and continuing in loop.
Modified: Lorzy/trunk/lib/Lorzy/Exception.pm
==============================================================================
--- Lorzy/trunk/lib/Lorzy/Exception.pm (original)
+++ Lorzy/trunk/lib/Lorzy/Exception.pm Fri Apr 24 03:55:57 2009
@@ -4,6 +4,9 @@
{ fields => ['details', 'stack'] },
'Lorzy::Exception::Native' =>
{ isa => 'Lorzy::Exception'},
+ 'Lorzy::Exception::Loop' =>
+ { isa => 'Lorzy::Exception',
+ fields => ['instruction'] },
'Lorzy::Exception::Params' =>
{ isa => 'Lorzy::Exception',
fields => ['missing', 'unwanted'] },
Added: Lorzy/trunk/lib/Lorzy/Expression/Break.pm
==============================================================================
--- (empty file)
+++ Lorzy/trunk/lib/Lorzy/Expression/Break.pm Fri Apr 24 03:55:57 2009
@@ -0,0 +1,22 @@
+package Lorzy::Expression::Break;
+use Moose;
+use MooseX::ClassAttribute;
+
+extends 'Lorzy::Expression';
+
+class_has signature => (
+ is => 'ro',
+ default => sub { {} } ,
+);
+
+sub evaluate {
+ my ($self, $evaluator) = @_;
+ $evaluator->throw_exception( 'Lorzy::Exception::Loop' => '',
+ instruction => 'break');
+}
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
+
Added: Lorzy/trunk/lib/Lorzy/Expression/Continue.pm
==============================================================================
--- (empty file)
+++ Lorzy/trunk/lib/Lorzy/Expression/Continue.pm Fri Apr 24 03:55:57 2009
@@ -0,0 +1,22 @@
+package Lorzy::Expression::Continue;
+use Moose;
+use MooseX::ClassAttribute;
+
+extends 'Lorzy::Expression';
+
+class_has signature => (
+ is => 'ro',
+ default => sub { {} } ,
+);
+
+sub evaluate {
+ my ($self, $evaluator) = @_;
+ $evaluator->throw_exception( 'Lorzy::Exception::Loop' => '',
+ instruction => 'continue');
+}
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
+
Modified: Lorzy/trunk/lib/Lorzy/Expression/ForEach.pm
==============================================================================
--- Lorzy/trunk/lib/Lorzy/Expression/ForEach.pm (original)
+++ Lorzy/trunk/lib/Lorzy/Expression/ForEach.pm Fri Apr 24 03:55:57 2009
@@ -34,7 +34,18 @@
my $nodes = $$list;
foreach (@$nodes) {
- $lambda->apply($evaluator, { $binding => $_ });
+ eval {
+ $lambda->apply($evaluator, { $binding => $_ });
+ };
+ my $e;
+ if ($e = Lorzy::Exception::Loop->caught()) {
+ last if $e->instruction eq 'break';
+ next if $e->instruction eq 'continue';
+ $evaluator->throw_exception( 'Lorzy::Exception' => 'Unknown loop instruction: '.$e->instruction );
+ }
+ elsif ($e = Lorzy::Exception->caught()) {
+ ref $e ? $e->rethrow : die $e;
+ }
}
}
Added: Lorzy/trunk/t/loop-control.t
==============================================================================
--- (empty file)
+++ Lorzy/trunk/t/loop-control.t Fri Apr 24 03:55:57 2009
@@ -0,0 +1,121 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use Test::More tests => 7;
+use Test::Exception;
+
+use_ok('Lorzy::Expression');
+use_ok('Lorzy::Evaluator');
+use_ok('Lorzy::Builder');
+use_ok('Lorzy::Lambda::Native');
+use_ok('Lorzy::FunctionArgument');
+
+my $builder = Lorzy::Builder->new();
+my $eval = Lorzy::Evaluator->new();
+$eval->load_package('Str');
+my $script =
+ $builder->defun(
+ ops => [
+ { name => 'List',
+ args => {
+ nodes => [ 1..10 ] } } ],
+ signature => { });
+
+$eval->set_global_symbol( 'get-list' => $script );
+
+my @remembered;
+$eval->set_global_symbol( 'remember' =>
+Lorzy::Lambda::Native->new(
+ body => sub {
+ my $args = shift;
+ push @remembered, $args->{what};
+ return 1;
+ },
+
+ signature => {
+ 'what' => Lorzy::FunctionArgument->new( name => 'what' => type => 'Str'),
+ }
+
+) );
+
+
+my $loop_code = $builder->defun(
+ ops => [
+ { name => 'IfThen',
+ args => {
+ 'if_true' => { name => 'Break' },
+ 'if_false' => '1',
+ 'condition' => {
+ name => 'Str.Eq',
+ args => {
+ arg1 => '6',
+ arg2 => {name => 'Symbol',
+ args => {symbol => 'what'} },
+ }
+ }
+ }
+ },
+ {name => 'remember', args => { what => { name => 'Symbol',
+ args => { symbol => 'what'} } } } ],
+ signature => {
+ 'what' => Lorzy::FunctionArgument->new( name => 'what' => type => 'Str') },
+);
+
+$eval->set_global_symbol( 'loop-code' => $loop_code );
+
+$eval->apply_script(
+ $builder->defun(
+ ops => [
+ { name => 'ForEach',
+ args => {
+ list => { name => 'get-list', args => {} },
+ binding => 'what',
+ do => {name => 'Symbol',
+ args => {symbol => 'loop-code'} },
+ }
+ } ],
+ signature => { }),
+ {});
+is_deeply(\@remembered, [1..5]);
+
+ at remembered = ();
+my $loop_code2 = $builder->defun(
+ ops => [
+ { name => 'IfThen',
+ args => {
+ 'if_true' => { name => 'Continue' },
+ 'if_false' => '1',
+ 'condition' => {
+ name => 'Str.Eq',
+ args => {
+ arg1 => '6',
+ arg2 => {name => 'Symbol',
+ args => {symbol => 'what'} },
+ }
+ }
+ }
+ },
+ {name => 'remember', args => { what => { name => 'Symbol',
+ args => { symbol => 'what'} } } } ],
+ signature => {
+ 'what' => Lorzy::FunctionArgument->new( name => 'what' => type => 'Str') },
+);
+
+
+$eval->set_global_symbol( 'loop-code' => $loop_code2 );
+
+$eval->apply_script(
+ $builder->defun(
+ ops => [
+ { name => 'ForEach',
+ args => {
+ list => { name => 'get-list', args => {} },
+ binding => 'what',
+ do => {name => 'Symbol',
+ args => {symbol => 'loop-code'} },
+ }
+ } ],
+ signature => { }),
+ {});
+is_deeply(\@remembered, [1..5,7..10]);
More information about the Bps-public-commit
mailing list