File Coverage

blib/lib/TestML1/Compiler.pm
Criterion Covered Total %
statement 55 59 93.2
branch 24 38 63.1
condition 3 6 50.0
subroutine 4 4 100.0
pod 0 2 0.0
total 86 109 78.9


line stmt bran cond sub pod time code
1 27     27   1253 use TestML1::Runtime;
  27         45  
  27         796  
2              
3             package TestML1::Compiler;
4              
5 27     27   114 use TestML1::Base;
  27         40  
  27         124  
6              
7             has code => ();
8             has data => ();
9             has text => ();
10             has directives => ();
11             has function => ();
12              
13             sub compile {
14 42     42 0 101 my ($self, $input) = @_;
15              
16 42         152 $self->preprocess($input, 'top');
17 42         181 $self->compile_code;
18 42         1453 $self->compile_data;
19              
20 42 50       121 if ($self->directives->{DumpAST}) {
21 0         0 XXX($self->function);
22             }
23              
24 42         106 $self->function->namespace->{TestML} = $self->directives->{TestML};
25              
26 42         103 $self->function->outer(TestML1::Function->new);
27 42         106 return $self->function;
28             }
29              
30             sub preprocess {
31 46     46 0 96 my ($self, $input, $top) = @_;
32              
33 46         733 my @parts = split /^((?:\%\w+.*|\#.*|\ *)\n)/m, $input;
34 46         82 $input = '';
35              
36             $self->{directives} = {
37 46         254 TestML => '',
38             DataMarker => '',
39             BlockMarker => '===',
40             PointMarker => '---',
41             };
42              
43 46         77 my $order_error = 0;
44 46         78 for my $part (@parts) {
45 778 100       997 next unless length($part);
46 600 100       1268 if ($part =~ /^(\#.*|\ *)\n/) {
47 321         345 $input .= "\n";
48 321         340 next;
49             }
50 279 100       602 if ($part =~ /^%(\w+)\s*(.*?)\s*\n/) {
51 50         178 my ($directive, $value) = ($1, $2);
52 50         83 $input .= "\n";
53 50 100       117 if ($directive eq 'TestML') {
54 42 50       177 die "Invalid TestML directive"
55             unless $value =~ /^\d+\.\d+\.\d+$/;
56             die "More than one TestML directive found"
57 42 50       163 if $self->directives->{TestML};
58             $self->directives->{TestML} =
59 42         216 TestML1::Str->new(value => $value);
60 42         104 next;
61             }
62 8 50       17 $order_error = 1 unless $self->directives->{TestML};
63 8 100       28 if ($directive eq 'Include') {
    50          
    0          
64 4 50       7 my $runtime = $TestML1::Runtime::Singleton
65             or die "Can't process Include. No runtime available";
66 4         21 my $include = ref($self)->new;
67 4         11 $include->preprocess($runtime->read_testml_file($value));
68 4         17 $input .= $include->text;
69             $self->directives->{DataMarker} =
70 4         9 $include->directives->{DataMarker};
71             $self->directives->{BlockMarker} =
72 4         7 $include->directives->{BlockMarker};
73             $self->directives->{PointMarker} =
74 4         6 $include->directives->{PointMarker};
75             die "Can't define %TestML in an Included file"
76 4 50       8 if $include->directives->{TestML};
77             }
78             elsif ($directive =~ /^(DataMarker|BlockMarker|PointMarker)$/) {
79 4         11 $self->directives->{$directive} = $value;
80             }
81             elsif ($directive =~ /^(DebugPegex|DumpAST)$/) {
82 0 0       0 $value = 1 unless length($value);
83 0         0 $self->directives->{$directive} = $value;
84             }
85             else {
86 0         0 die "Unknown TestML directive '$directive'";
87             }
88             }
89             else {
90 229 50 66     511 $order_error = 1 if $input and not $self->directives->{TestML};
91 229         474 $input .= $part;
92             }
93             }
94              
95 46 100       100 if ($top) {
96             die "No TestML directive found"
97 42 50       106 unless $self->directives->{TestML};
98 42 50       121 die "%TestML directive must be the first (non-comment) statement"
99             if $order_error;
100              
101             my $DataMarker =
102             $self->directives->{DataMarker} ||=
103 42   33     89 $self->directives->{BlockMarker};
104 42 100       212 if ((my $split = index($input, "\n$DataMarker")) >= 0) {
105 29         196 $self->{code} = substr($input, 0, $split + 1);
106 29         135 $self->{data} = substr($input, $split + 1);
107             }
108             else {
109 13         35 $self->{code} = $input;
110 13         42 $self->{data} = '';
111             }
112             }
113             else {
114 4         9 $self->{text} = $input;
115             }
116             }
117              
118             1;