File Coverage

blib/lib/Lox.pm
Criterion Covered Total %
statement 45 71 63.3
branch 7 18 38.8
condition n/a
subroutine 11 16 68.7
pod 0 8 0.0
total 63 113 55.7


line stmt bran cond sub pod time code
1             package Lox;
2 1     1   62867 use strict;
  1         2  
  1         36  
3 1     1   5 use warnings;
  1         54  
  1         34  
4 1     1   496 use Lox::AstPrinter;
  1         1  
  1         35  
5 1     1   390 use Lox::Interpreter;
  1         3  
  1         31  
6 1     1   397 use Lox::Parser;
  1         2  
  1         26  
7 1     1   367 use Lox::Resolver;
  1         2  
  1         59  
8 1     1   378 use Lox::Scanner;
  1         2  
  1         28  
9 1     1   5 use Lox::TokenType;
  1         2  
  1         625  
10             our $VERSION = 0.02;
11              
12             my $had_error = undef;
13              
14             sub run_file {
15 0     0 0 0 my ($path, $debug_mode) = @_;
16 0 0       0 open my $fh, '<', $path or die "Error opening $path: $!";
17 0         0 my $text = do { local $/; <$fh> };
  0         0  
  0         0  
18 0         0 my $interpreter = Lox::Interpreter->new;
19 0         0 Lox::eval($interpreter, $text, $debug_mode);
20 0 0       0 if ($had_error) {
21 0         0 exit 65;
22             }
23             }
24              
25             sub run_prompt {
26 0     0 0 0 my ($debug_mode) = @_;
27 0         0 print "Welcome to Perl-Lox version $VERSION\n> ";
28 0         0 my $interpreter = Lox::Interpreter->new;
29 0         0 while (my $line = <>) {
30 0         0 Lox::eval($interpreter, $line, $debug_mode);
31 0         0 undef $had_error;
32 0         0 print "> ";
33             }
34             }
35              
36             sub eval {
37 2     2 0 775 my ($interpreter, $source, $debug_mode) = @_;
38              
39 2         7 my $tokens = scan($source, $debug_mode);
40 2 50       6 return if $had_error;
41              
42 2         3 my $stmts = parse($tokens, $debug_mode);
43 2 50       6 return if $had_error;
44              
45 2         10 Lox::Resolver->new($interpreter)->run($stmts);
46 2 50       9 return if $had_error;
47              
48 2         6 $interpreter->interpret($stmts);
49             }
50              
51             sub scan {
52 2     2 0 3 my ($source, $debug_mode) = @_;
53 2         12 my $scanner = Lox::Scanner->new({source => $source});
54 2         4 eval { $scanner->scan_tokens };
  2         6  
55 2 50       6 if ($@) {
56 0         0 die "Unexpected error: $@";
57             }
58 2 50       4 $scanner->print if $debug_mode;
59 2         6 return $scanner->tokens;
60             }
61              
62             sub parse {
63 2     2 0 3 my ($tokens, $debug_mode) = @_;
64 2         13 my $parser = Lox::Parser->new({tokens => $tokens});
65 2         6 my $stmts = $parser->parse;
66 2 50       6 if ($parser->errors->@*) {
67 0         0 error(@$_) for ($parser->{errors}->@*);
68             }
69 2 50       4 print Lox::AstPrinter->new->print_tree($stmts), "\n" if $debug_mode;
70 2         8 return $stmts;
71             }
72              
73             sub runtime_error {
74 0     0 0   my ($token, $message) = @_;
75 0           report($token->{line}, "at '$token->{lexeme}'", $message);
76 0           exit 65;
77             }
78              
79             sub error {
80 0     0 0   my ($token, $message) = @_;
81 0           $had_error = 1;
82 0           report($token->{line}, "at '$token->{lexeme}'", $message);
83             }
84              
85             sub report {
86 0     0 0   my ($line, $where, $message) = @_;
87 0           printf "[Line %s] Error %s: %s.\n", $line, $where, $message;
88             }
89              
90             1;
91             __END__