File Coverage

blib/lib/Language/AttributeGrammar/Thunk.pm
Criterion Covered Total %
statement 25 25 100.0
branch 9 10 90.0
condition 1 3 33.3
subroutine 5 5 100.0
pod 3 3 100.0
total 43 46 93.4


line stmt bran cond sub pod time code
1             package Language::AttributeGrammar::Thunk;
2              
3 5     5   38 use Carp::Clan '^Language::AttributeGrammar';
  5         12  
  5         43  
4 5     5   941 use Perl6::Attributes;
  5         13  
  5         29  
5              
6             =head1 NAME
7              
8             Language::AttributeGrammar::Thunk - Delayed code logic
9              
10             =head1 DESCRIPTION
11              
12             This is a four stage thunk.
13              
14             stage 1: code unset
15             stage 2: code set, unevaluated
16             stage 3: code being evaluated
17             stage 4: code evaluated and return value stored
18              
19             =over
20              
21             =cut
22              
23             sub new {
24 782     782 1 1122 my ($class, $code, $attr, $at) = @_;
25 782 50 33     6688 my $self = bless {
26             stage => ($code ? 2 : 1),
27             code => $code,
28             value => undef,
29             attr => $attr,
30             at => $at,
31             } => ref $class || $class;
32 782         2970 $self;
33             }
34              
35             =item * new($class, ?$code, ?$attr, ?$at)
36              
37             Creates a new thunk object. If $code, $attr, and $at are specified,
38             initializes the object via C.
39              
40             =cut
41              
42             sub set {
43 780     780 1 1219 my ($self, $code, $attr, $at) = @_;
44 780 100       1827 unless ($.stage == 1) {
45 2         19 croak "Attribute '$attr' defined more than once at $at and $.at";
46             }
47 778         1242 $.at = $at;
48 778         975 $.code = $code;
49 778         5702 $.stage++;
50             }
51              
52             =item * $thunk->set($code, $attr, $at)
53              
54             Set the code for a thunk. $attr is the name of the attribute that this code is
55             evaluating (for example "Cons:length") and $at is a description of the location
56             at which the thunk was defined (for example "grammar.pl line 42"). Both of the
57             latter two are only used for diagnostic purposes. This method is only valid
58             when the thunk is in stage 1 (and it moves it to stage 2).
59              
60             =cut
61              
62             sub get {
63 816     816 1 1277 my ($self, $attr, $at) = @_;
64 816 100       2752 if ($.stage == 4) {
    100          
    100          
65 100         286 $.value;
66             }
67             elsif ($.stage == 2) {
68 713         985 $.stage++;
69 713         4717 $.value = $.code->();
70 705         1069 undef $.code;
71 705         2130 $.stage++;
72 705         3430 $.value;
73             }
74             elsif ($.stage == 3) {
75 1         8 croak "Infinite loop on attribute '$attr' at $at";
76             }
77             else {
78 2         14 croak "Attribute '$attr' not defined at $at";
79             }
80             }
81              
82             =item * $thunk->get($attr, $at)
83              
84             valuate a thunk. $attr is the name of the attribute that is being fetched,
85             and $at is a description of the location at which it is being fetched. In
86             stage 1 it fails because there is no code to evaluate, and in stage 3 it fails
87             because this implies that an infinite loop would occur. After successful
88             execution of this method, the thunk is in stage 4.
89              
90             =cut
91              
92             1;
93              
94             =back
95              
96             =head1 SEE ALSO
97              
98             L, L