File Coverage

blib/lib/Language/LispPerl/Role/BuiltIns/Coro.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Language::LispPerl::Role::BuiltIns::Coro;
2             $Language::LispPerl::Role::BuiltIns::Coro::VERSION = '0.005';
3 1     1   1244 use Moose::Role;
  1         3446  
  1         3  
4              
5 1     1   4315 use Coro;
  0            
  0            
6              
7             use Language::LispPerl::Atom;
8             use Language::LispPerl::Seq;
9              
10             =head1 NAME
11              
12             Language::LispPerl::Role::BuiltIns::Coro - A role with coro primitives for the BuiltIns objects.
13              
14             =head1 SYNOPSIS
15              
16             my $lisp = Language::LispPerl::Evaler->new();
17              
18             $lisp->builtins()->apply_role('Language::LispPerl::Role::BuiltIns::Coro');
19              
20             .. lisp now implements the coro functions.
21              
22             =head2 FUNCTIONS
23              
24             To be documented. Look at the source code for now..
25              
26             =cut
27              
28             my $_CORO_FUNCTIONS = {
29              
30             # Coro stuff
31             "coro" => \&_impl_coro,
32             "coro-suspend" => \&_impl_coro_suspend,
33             "coro-sleep" => \&_impl_coro_sleep,
34             "coro-yield" => \&_impl_coro_yield,
35             "coro-resume" => \&_impl_coro_resume,
36             "coro-wake" => \&_impl_coro_wake,
37             "coro-join" => \&_impl_coro_join,
38             "coro-current" => \&_impl_coro_current,
39             "coro-main" => \&_impl_coro_main,
40             };
41              
42             around 'has_function' => sub {
43             my ( $orig, $self, $fname, @rest ) = @_;
44              
45             if ( my $f = $_CORO_FUNCTIONS->{$fname} ) {
46             return $f;
47             }
48             return $self->$orig( $fname, @rest );
49             };
50              
51             sub _impl_coro {
52             my ( $self, $ast, $symbol ) = @_;
53             $ast->error("coro expects 1 argument") if $ast->size() != 2;
54             my $b = $self->evaler()->_eval( $ast->second() );
55             $ast->error( "core expects a function as argument but got " . $b->type() )
56             if $b->type() ne "function";
57             my $coro = new Coro sub {
58             my $evaler = $self->evaler()->new_instance();
59             my $fc = Language::LispPerl::Seq->new({ type => "list" });
60             $fc->append($b);
61             $evaler->_eval($fc);
62             };
63             $coro->ready();
64             return Language::LispPerl::Atom->new({type => "coroutine", value => $coro });
65             }
66              
67             sub _impl_coro_suspend {
68             my ( $self, $ast, $symbol ) = @_;
69             $ast->error("coro-suspend expects 1 argument") if $ast->size() != 2;
70             my $coro = $self->evaler()->_eval( $ast->second() );
71             $ast->error( "coro-suspend expects a coroutine as argument but got "
72             . $coro->type() )
73             if $coro->type() ne "coroutine";
74             $coro->value()->suspend();
75             return $coro;
76             }
77              
78             sub _impl_coro_sleep {
79             my ( $self, $ast ) = @_;
80             $ast->error("coro-sleep expects 0 argument") if $ast->size != 1;
81             $Coro::current->suspend();
82             cede();
83             return Language::LispPerl::Atom->new({ type => "coroutine", value => $Coro::current });
84             }
85              
86             sub _impl_coro_yield {
87             my ( $self, $ast ) = @_;
88             $ast->error("coro-yield expects 0 argument") if $ast->size() != 1;
89             cede;
90             return Language::LispPerl::Atom->new({ type => "coroutine", value => $Coro::current });
91             }
92              
93             sub _impl_coro_resume {
94             my ( $self, $ast ) = @_;
95             $ast->error("coro-resume expects 1 argument") if $ast->size() != 2;
96             my $coro = $self->evaler()->_eval( $ast->second() );
97             $ast->error(
98             "coro-resume expects a coroutine as argument but got " . $coro->type() )
99             if $coro->type() ne "coroutine";
100             $coro->value()->resume();
101             $coro->value()->cede_to();
102             return $coro;
103             }
104              
105             sub _impl_coro_wake {
106             my ( $self, $ast ) = @_;
107             $ast->error("coro-wake expects 1 argument") if $ast->size() != 2;
108             my $coro = $self->evaler()->_eval( $ast->second() );
109             $ast->error(
110             "coro-wake expects a coroutine as argument but got " . $coro->type() )
111             if $coro->type() ne "coroutine";
112             $coro->value()->resume();
113             return $coro;
114             }
115              
116             sub _impl_coro_join {
117             my ( $self, $ast ) = @_;
118             $ast->error("join-coro expects 1 argument") if $ast->size() != 2;
119             my $coro = $self->evaler()->_eval( $ast->second() );
120             $ast->error(
121             "join-coro expects a coroutine as argument but got " . $coro->type() )
122             if $coro->type() ne "coroutine";
123             $coro->value()->join();
124             return $coro;
125             }
126              
127             sub _impl_coro_current {
128             my ( $self, $ast ) = @_;
129             $ast->error("coro-current expects 0 argument") if $ast->size() != 1;
130             return Language::LispPerl::Atom->new({ type => "coroutine", value => $Coro::current });
131             }
132              
133             sub _impl_coro_main {
134             my ( $self, $ast ) = @_;
135             $ast->error("coro-main expects 0 argument") if $ast->size() != 1;
136             return Language::LispPerl::Atom->new({ type => "coroutine", value => $Coro::main });
137             }
138              
139             1;