File Coverage

blib/lib/RPerl/Operation/Statement/OperatorVoid/Print.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             # [[[ HEADER ]]]
2             package RPerl::Operation::Statement::OperatorVoid::Print;
3 5     5   34 use strict;
  5         16  
  5         134  
4 5     5   24 use warnings;
  5         15  
  5         107  
5 5     5   26 use RPerl::AfterSubclass;
  5         10  
  5         666  
6             our $VERSION = 0.004_000;
7              
8             # [[[ OO INHERITANCE ]]]
9 5     5   36 use parent qw(RPerl::Operation::Statement::OperatorVoid);
  5         11  
  5         29  
10 5     5   305 use RPerl::Operation::Statement::OperatorVoid;
  5         18  
  5         3944  
11              
12             # [[[ CRITICS ]]]
13             ## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls) # USER DEFAULT 1: allow numeric values & print operator
14             ## no critic qw(RequireInterpolationOfMetachars) # USER DEFAULT 2: allow single-quoted control characters & sigils
15              
16             # [[[ OO PROPERTIES ]]]
17             our hashref $properties = {};
18              
19             # [[[ SUBROUTINES & OO METHODS ]]]
20              
21             our string_hashref::method $ast_to_rperl__generate = sub {
22             ( my object $self, my string_hashref $modes) = @_;
23             my string_hashref $rperl_source_group = { PMC => q{} };
24             my string_hashref $rperl_source_subgroup;
25              
26             # RPerl::diag( 'in OperatorVoid::Print->ast_to_rperl__generate(), received $self = ' . "\n" . RPerl::Parser::rperl_ast__dump($self) . "\n" );
27              
28             my string $self_class = ref $self;
29             if ( $self_class eq 'OperatorVoid_117' ) { # OperatorVoid -> OP01_PRINT OPTIONAL-31 ListElements ';'
30             my string $print = $self->{children}->[0];
31             my object $stdout_stderr_optional = $self->{children}->[1];
32             my object $list_elements = $self->{children}->[2];
33             my string $semicolon = $self->{children}->[3];
34              
35             # RPerl::diag( 'in OperatorVoid::Print->ast_to_rperl__generate(), have $stdout_stderr_optional = ' . "\n" . RPerl::Parser::rperl_ast__dump($stdout_stderr_optional) . "\n" );
36              
37             $rperl_source_group->{PMC} .= $print . q{ };
38              
39             if ( exists $stdout_stderr_optional->{children}->[0] ) {
40             if ( ( $stdout_stderr_optional->{children}->[0]->{attr} ne '{*STDOUT}' ) and ( $stdout_stderr_optional->{children}->[0]->{attr} ne '{*STDERR}' ) ) {
41             die RPerl::Parser::rperl_rule__replace( 'ERROR ECOGEASRP28, CODE GENERATOR, ABSTRACT SYNTAX TO RPERL: output stream '
42             . $stdout_stderr_optional->{children}->[0]->{attr}
43             . ' found where {*STDOUT} or {*STDERR} expected, dying' )
44             . "\n";
45             }
46              
47             # DEV NOTE: STDOUT & STDERR are generated below, they are only grammar tokens, not grammar rules, so they do not get their own classes, the following do not exist:
48             # RPerl::InputOutput::Stderr & RPerl::InputOutput::Stdout
49             $rperl_source_group->{PMC} .= $stdout_stderr_optional->{children}->[0]->{attr} . q{ };
50             }
51              
52             $rperl_source_subgroup = $list_elements->ast_to_rperl__generate($modes);
53             RPerl::Generator::source_group_append( $rperl_source_group, $rperl_source_subgroup );
54             $rperl_source_group->{PMC} .= $semicolon . "\n";
55             }
56             elsif ( $self_class eq 'OperatorVoid_118' ) { # OperatorVoid -> OP01_PRINT FHREF_SYMBOL_BRACES ListElements ';'
57             my string $print = $self->{children}->[0];
58             my string $fhref_symbol_braces = $self->{children}->[1];
59             my object $list_elements = $self->{children}->[2];
60             my string $semicolon = $self->{children}->[3];
61              
62             $rperl_source_group->{PMC} .= $print . q{ } . $fhref_symbol_braces . q{ };
63             $rperl_source_subgroup = $list_elements->ast_to_rperl__generate($modes);
64             RPerl::Generator::source_group_append( $rperl_source_group, $rperl_source_subgroup );
65             $rperl_source_group->{PMC} .= $semicolon . "\n";
66             }
67             else {
68             die RPerl::Parser::rperl_rule__replace( 'ERROR ECOGEASRP00, CODE GENERATOR, ABSTRACT SYNTAX TO RPERL: Grammar rule '
69             . $self_class
70             . ' found where OperatorVoid_117 or OperatorVoid_118 expected, dying' )
71             . "\n";
72             }
73              
74             return $rperl_source_group;
75             };
76              
77             our string_hashref::method $ast_to_cpp__generate__CPPOPS_PERLTYPES = sub {
78             ( my object $self, my string_hashref $modes) = @_;
79             my string_hashref $cpp_source_group = { CPP => q{// <<< RP::O::S::OV::P __DUMMY_SOURCE_CODE CPPOPS_PERLTYPES >>>} . "\n" };
80              
81             #...
82             return $cpp_source_group;
83             };
84              
85             our string_hashref::method $ast_to_cpp__generate__CPPOPS_CPPTYPES = sub {
86             ( my object $self, my string_hashref $modes) = @_;
87             my string_hashref $cpp_source_group = { CPP => q{} };
88             my string_hashref $cpp_source_subgroup;
89              
90             # RPerl::diag( 'in OperatorVoid::Print->ast_to_cpp__generate__CPPOPS_CPPTYPES(), received $self = ' . "\n" . RPerl::Parser::rperl_ast__dump($self) . "\n" );
91              
92             # NEED FIX PARALLEL: temporarily disabled print operators while inside parallel loop to avoid pluto polycc error
93             if ($modes->{_inside_parallel_loop}) {
94             return $cpp_source_group;
95             }
96              
97             my string $self_class = ref $self;
98             if ( $self_class eq 'OperatorVoid_117' ) { # OperatorVoid -> OP01_PRINT OPTIONAL-31 ListElements ';'
99             my object $stdout_stderr_optional = $self->{children}->[1];
100             my object $list_elements = $self->{children}->[2];
101             my string $semicolon = $self->{children}->[3];
102              
103             # RPerl::diag( 'in OperatorVoid::Print->ast_to_cpp__generate__CPPOPS_CPPTYPES(), have $stdout_stderr_optional = ' . "\n" . RPerl::Parser::rperl_ast__dump($stdout_stderr_optional) . "\n" );
104             # RPerl::diag( 'in OperatorVoid::Print->ast_to_cpp__generate__CPPOPS_CPPTYPES(), have $list_elements = ' . "\n" . RPerl::Parser::rperl_ast__dump($list_elements) . "\n" );
105              
106             if ( exists $stdout_stderr_optional->{children}->[0] ) {
107             if ( $stdout_stderr_optional->{children}->[0]->{attr} eq '{*STDOUT}' ) {
108             # DEV NOTE, CORRELATION #rp100: C++ cout w/ double-less-than << input list separators is equivalent to Perl print w/ comma separators
109             # $cpp_source_group->{CPP} .= 'cout << ';
110             $cpp_source_group->{CPP} .= 'print ';
111             }
112             elsif ( $stdout_stderr_optional->{children}->[0]->{attr} eq '{*STDERR}' ) {
113             # DEV NOTE, CORRELATION #rp101: C++ cerr w/ double-less-than << input list separators is equivalent to Perl print {*STDERR} w/ comma separators
114             # $cpp_source_group->{CPP} .= 'cerr << ';
115             $cpp_source_group->{CPP} .= 'prerr ';
116             }
117             else {
118             die RPerl::Parser::rperl_rule__replace( 'ERROR ECOGEASCP28, CODE GENERATOR, ABSTRACT SYNTAX TO C++: output stream '
119             . $stdout_stderr_optional->{children}->[0]->{attr}
120             . ' found where {*STDOUT} or {*STDERR} expected, dying' )
121             . "\n";
122             }
123             }
124             else {
125             # $cpp_source_group->{CPP} .= 'cout << ';
126             $cpp_source_group->{CPP} .= 'print ';
127             }
128              
129             # DEV NOTE: always use endl instead of "\n" for cout, because Perl immediately flushes buffers on STDOUT newline characters
130             # http://perl.plover.com/FAQs/Buffering.html
131             # When a filehandle is attached to the terminal, as STDOUT is here, it is in line buffered mode by default.
132             # A filehandle in line buffered mode has two special properties: It's flushed automatically whenever you print a newline character to it,
133             # and it's flushed automatically whenever you read from the terminal.
134              
135             # save to stack of saved flags, when needed
136             if ((exists $modes->{_inside_print_operator}) and (defined $modes->{_inside_print_operator})) {
137             if ((not exists $modes->{_inside_print_operator_saved}) or (not defined $modes->{_inside_print_operator_saved})) {
138             $modes->{_inside_print_operator_saved} = [];
139             }
140             push @{$modes->{_inside_print_operator_saved}}, $modes->{_inside_print_operator};
141             }
142             $modes->{_inside_print_operator} = 1;
143              
144             $cpp_source_subgroup = $list_elements->ast_to_cpp__generate__CPPOPS_CPPTYPES($modes);
145             RPerl::Generator::source_group_append( $cpp_source_group, $cpp_source_subgroup );
146             # replace closing "\n" with endl
147             if ((substr $cpp_source_group->{CPP}, -4, 4) eq q{"\n"}) {
148             # if (0) {
149             substr $cpp_source_group->{CPP}, -4, 4, q{};
150             $cpp_source_group->{CPP} .= 'endl';
151             }
152             $cpp_source_group->{CPP} .= $semicolon . "\n";
153              
154             # restore from stack of saved flags, when needed
155             delete $modes->{_inside_print_operator};
156             if ((exists $modes->{_inside_print_operator_saved}) and (defined $modes->{_inside_print_operator_saved}) and (scalar $modes->{_inside_print_operator_saved})) {
157             $modes->{_inside_print_operator} = pop @{$modes->{_inside_print_operator_saved}};
158             if (not scalar $modes->{_inside_print_operator_saved}) { delete $modes->{_inside_print_operator_saved}; }
159             }
160             }
161             elsif ( $self_class eq 'OperatorVoid_118' ) { # OperatorVoid -> OP01_PRINT FHREF_SYMBOL_BRACES ListElements ';'
162             $cpp_source_group->{CPP} .= '// <<< RP::O::S::OV::P __DUMMY_SOURCE_CODE CPPOPS_CPPTYPES >>>' . "\n";
163             }
164             else {
165             die RPerl::Parser::rperl_rule__replace( 'ERROR ECOGEASCP00, CODE GENERATOR, ABSTRACT SYNTAX TO C++: Grammar rule '
166             . $self_class
167             . ' found where OperatorVoid_117 or OperatorVoid_118 expected, dying' )
168             . "\n";
169             }
170              
171             # RPerl::diag( 'in OperatorVoid::Print->ast_to_cpp__generate__CPPOPS_CPPTYPES(), about to return $cpp_source_group = ' . "\n" . RPerl::Parser::rperl_ast__dump($cpp_source_group) . "\n" );
172             return $cpp_source_group;
173             };
174              
175             1; # end of class