File Coverage

blib/lib/Dallycot/AST/Sequence.pm
Criterion Covered Total %
statement 39 117 33.3
branch 2 20 10.0
condition 1 3 33.3
subroutine 8 16 50.0
pod 0 8 0.0
total 50 164 30.4


line stmt bran cond sub pod time code
1             package Dallycot::AST::Sequence;
2             our $AUTHORITY = 'cpan:JSMITH';
3              
4             # ABSTRACT: Creates a new execution context for child nodes
5              
6 23     23   1130 use strict;
  23         33  
  23         873  
7 23     23   101 use warnings;
  23         32  
  23         559  
8              
9 23     23   103 use utf8;
  23         212  
  23         148  
10 23     23   441 use parent 'Dallycot::AST';
  23         29  
  23         151  
11              
12 23     23   1831 use List::Util qw(any);
  23         30  
  23         1660  
13 23     23   112 use Promises qw(deferred);
  23         31  
  23         175  
14 23     23   5507 use Scalar::Util qw(blessed);
  23         38  
  23         21608  
15              
16             sub new {
17 3     3 0 9 my ( $class, @expressions ) = @_;
18              
19 3 50       8 my @declarations = grep { blessed($_) && $_->is_declarative } @expressions;
  6         53  
20 3 50       8 my @statements = grep { blessed($_) && !$_->is_declarative } @expressions;
  6         34  
21              
22 3         8 my @assignment_names = grep {defined} map { $_->identifier } @declarations;
  4         11  
  4         17  
23              
24 0         0 my %namespace_prefixes
25 3         8 = map { $_->prefix => $_->namespace } grep { $_->isa('Dallycot::AST::XmlnsDef') } @declarations;
  4         33  
26              
27 3         7 @declarations = grep { !$_->isa('Dallycot::AST::XmlnsDef') } @declarations;
  4         17  
28              
29 3         7 my @namespace_searches = map { $_->namespace } grep { $_->isa('Dallycot::AST::Uses') } @declarations;
  0         0  
  4         22  
30              
31 3         6 @declarations = grep { !$_->isa('Dallycot::AST::Uses') } @declarations;
  4         15  
32              
33 3   33     15 $class = ref $class || $class;
34              
35             return
36 3         19 bless [ \@declarations, \@statements, \@assignment_names, \%namespace_prefixes,
37             \@namespace_searches ] => $class;
38             }
39              
40             sub to_rdf {
41 0     0 0   my($self, $model) = @_;
42              
43 0           my $bnode = $model -> bnode;
44 0           my $child_model = $model -> child_model;
45              
46 0 0         while(my($ns, $href) = each %{$self->[3]||{}}) {
  0            
47 0 0         $child_model -> add_namespace_mapping(
48             $ns => (blessed $href ? $href -> value : $href)
49             );
50             }
51              
52 0 0         my @uses = @{$self -> [4]||[]};
  0            
53 0           $child_model -> add_search_path(@uses);
54              
55 0           foreach my $decl (@{$self->[0]}) {
  0            
56 0           $decl -> to_rdf($child_model)
57             }
58              
59             # actually, we need to build out a lambda for each one and discard
60             # its argument, something like:
61             # { expression[n] }( { expression[n-1] }( { expression[n-2] }( ... ) ) )
62             #
63             # run( a, b ) => b
64             # run( run( expression[1] ), expression[0] )
65             # run( run( expression[2] ), expression[1] ), expression[0] )
66             #
67             # last({ (#2)() }/2 << [ sequence of expressions ])
68             #
69             # applying <last> to <foldl> applied to a list of expressions
70             # with each expression being a closure over what's declared in this scope
71             # and parent scopes
72             #
73 0           my @expressions = @{$self->[1]};
  0            
74              
75 0 0         return $bnode unless @expressions;
76              
77 0 0         if(@expressions == 1) {
78 0           return $expressions[0] -> to_rdf($child_model);
79             }
80              
81 0           my $expression_list = $child_model -> model -> add_list(
82 0           map { $_ -> to_rdf($child_model) } @expressions
83             );
84              
85 0           $child_model -> apply(
86             $child_model -> meta_uri('loc:execute-list'),
87             [ $expression_list ]
88             );
89              
90 0           return $bnode;
91             }
92              
93             sub to_string {
94 0     0 0   my ($self) = @_;
95 0           return join( "; ",
96 0           ( map { 'uses "' . $_ . '"' } @{ $self->[4] } ),
  0            
97 0           ( map { "ns:$_ := \"" . $self->[3]->{$_} . "\"" } keys %{ $self->[3] } ),
  0            
98 0           map { $_->to_string } @{ $self->[0] },
  0            
99 0           @{ $self->[1] } );
100             }
101              
102             sub simplify {
103 0     0 0   my ($self) = @_;
104              
105 0           return $self->new( map { $_->simplify } @{ $self->[0] }, @{ $self->[1] } );
  0            
  0            
  0            
106             }
107              
108             sub check_for_common_mistakes {
109 0     0 0   my ($self) = @_;
110              
111 0           my @warnings;
112              
113             # if(any { $_ -> isa('Dallycot::AST::Equality') } @{$self}[1][0..-2]) {
114             # push @warnings, 'Did you mean to assign instead of test for equality?';
115             # }
116             # if(any { !$_ -> isa('Dallycot::AST::Equality') && $_ -> isa('Dallycot::AST::ComparisonBase') } @{$self}[1][0..-2]) {
117             # push @warnings, 'Result of comparison is not used.';
118             # }
119             # push @warnings, map { $_ -> check_for_common_mistakes } @$self;
120 0           return @warnings;
121             }
122              
123             sub execute {
124 0     0 0   my ( $self, $engine ) = @_;
125              
126 0           my $child_scope = $engine->with_child_scope();
127 0 0         my $var_scope = $engine->has_parent ? $child_scope : $engine;
128              
129 0           foreach my $ident ( @{ $self->[2] } ) {
  0            
130 0           $var_scope->add_assignment($ident);
131             }
132              
133             # wait for namespaces to load
134 0           Dallycot::Registry->instance->register_used_namespaces( @{$self->[4]} )->then(sub {
135 0     0     $var_scope->append_namespace_search_path( @{ $self->[4] } );
  0            
136              
137 0           for my $ns ( keys %{ $self->[3] } ) {
  0            
138 0           $var_scope->add_namespace( $ns, $self->[3]->{$ns} );
139             }
140              
141 0           my $assignments = $var_scope->collect( @{ $self->[0] } );
  0            
142              
143 0 0         if(@{$self->[1]}) {
  0            
144 0           $assignments->done(sub{});
  0            
145 0           return $var_scope->execute( @{ $self->[1] } );
  0            
146             }
147             else {
148             return $assignments->then(sub {
149 0           my($last) = pop @_;
150 0 0         if($last) {
151 0           return $last;
152             }
153             else {
154 0           return $engine -> UNDEFINED;
155             }
156 0           });
157             }
158 0           });
159             }
160              
161             sub identifiers {
162 0     0 0   my ($self) = @_;
163              
164 0           my @identifiers = map { $_->identifiers } $self->child_nodes;
  0            
165 0           my %assignments = map { $_ => 1 } @{ $self->[2] };
  0            
  0            
166 0           return grep { !$assignments{$_} } @identifiers;
  0            
167             }
168              
169             sub child_nodes {
170 0     0 0   my ($self) = @_;
171              
172 0           return ( @{ $self->[0] }, @{ $self->[1] } );
  0            
  0            
173             }
174              
175             1;