File Coverage

blib/lib/WAP/wmls/node.pm
Criterion Covered Total %
statement 120 728 16.4
branch 0 78 0.0
condition 0 135 0.0
subroutine 40 140 28.5
pod 0 11 0.0
total 160 1092 14.6


line stmt bran cond sub pod time code
1 1     1   729 use strict;
  1         2  
  1         40  
2 1     1   5 use warnings;
  1         2  
  1         888  
3            
4             #
5             # WMLScript Language Specification Version 1.1
6             #
7            
8             package WAP::wmls::node;
9            
10             sub new {
11 0     0 0   my $proto = shift;
12 0   0       my $class = ref($proto) || $proto;
13 0           my $self = {};
14 0           bless $self, $class;
15 0           my ($op) = @_;
16 0           $self->{OpCode} = $op;
17 0           $self->{Next} = undef;
18 0           $self->{Prev} = undef;
19 0           $self->{Last} = $self;
20 0           $self->{Deleted} = 0;
21 0           return $self;
22             }
23            
24             sub del {
25 0     0 0   my $self = shift;
26 0           $self->{Deleted} = 1;
27 0           $self->{OpCode}->{Deleted} = 1;
28 0           return $self;
29             }
30            
31             sub configure {
32 0     0 0   my $self = shift;
33 0           $self->{OpCode}->configure(@_);
34 0           return $self;
35             }
36            
37             sub concat {
38 0     0 0   my $node1 = shift;
39 0           my ($node2) = @_;
40 0           $node1->{Last}->{Next} = $node2;
41 0           $node2->{Prev} = $node1->{Last};
42 0           $node1->{Last} = $node2->{Last};
43 0           return $node1;
44             }
45            
46             sub insert {
47 0     0 0   my $node1 = shift;
48 0           my ($node2) = @_;
49 0           $node2->{Next} = $node1->{Next};
50 0           $node2->{Prev} = $node1;
51 0 0         if (defined $node1->{Next}) {
52 0           $node1->{Next}->{Prev} = $node2;
53             }
54 0           $node1->{Next} = $node2;
55 0           return;
56             }
57            
58             sub visit {
59 0     0 0   my $self = shift;
60 0           my $visitor = shift;
61 0           for (my $node = $self; defined $node; $node = $node->{Next}) {
62 0           my $opcode = $node->{OpCode};
63 0           my $class = ref $opcode;
64 0           my $func = 'visit' . substr($class, rindex($class, ':') + 1);
65 0           $visitor->$func($opcode, @_);
66             }
67 0           return;
68             }
69            
70             sub visitActive {
71 0     0 0   my $self = shift;
72 0           my $visitor = shift;
73 0           for (my $node = $self; defined $node; $node = $node->{Next}) {
74 0 0         next if ($node->{Deleted});
75 0           my $opcode = $node->{OpCode};
76 0           my $class = ref $opcode;
77 0           my $func = 'visit' . substr($class, rindex($class, ':') + 1);
78 0           $visitor->$func($opcode, @_);
79             }
80 0           return;
81             }
82            
83             sub getFirstActive {
84 0     0 0   my $self = shift;
85 0           my $node;
86 0   0       for ( $node = $self;
87             defined($node) and $node->{Deleted};
88             $node = $node->{Next} ) {}
89 0           return $node;
90             }
91            
92             sub getLastActive {
93 0     0 0   my $self = shift;
94 0           my $node;
95 0           for ( $node = $self->{Last};
96             defined($node->{Next});
97             $node = $node->{Next} ) {}
98 0   0       for ( ;
99             defined($node) and $node->{Deleted};
100             $node = $node->{Prev} ) {}
101 0           return $node;
102             }
103            
104             sub getNextActive {
105 0     0 0   my $self = shift;
106 0           my $node;
107 0   0       for ( $node = $self->{Next};
108             defined($node) and $node->{Deleted};
109             $node = $node->{Next} ) {}
110 0           return $node;
111             }
112            
113             sub getPrevActive {
114 0     0 0   my $self = shift;
115 0           my $node;
116 0   0       for ( $node = $self->{Prev};
117             defined $node and $node->{Deleted};
118             $node = $node->{Prev} ) {}
119 0           return $node;
120             }
121            
122             ###############################################################################
123            
124             package WAP::wmls::OpCode;
125            
126             sub new {
127 0     0     my $proto = shift;
128 0   0       my $class = ref($proto) || $proto;
129 0           my $parser = shift;
130 0           my %attr = @_;
131 0           my $self = \%attr;
132 0           foreach (keys %attr) {
133 0 0         unless (defined $self->{$_}) {
134 0           delete $self->{$_};
135             }
136             }
137 0           $self->{Lineno} = $parser->YYData->{lineno};
138 0           return $self;
139             }
140            
141             sub isa {
142 0     0     my $self = shift;
143 0           my ($type) = @_;
144 0           return UNIVERSAL::isa($self, 'WAP::wmls::' . $type);
145             }
146            
147             sub configure {
148 0     0     my $self = shift;
149 0           my %attr = @_;
150 0           while ( my ($key, $value) = each(%attr) ) {
151 0 0         if (defined $value) {
152 0           $self->{$key} = $value;
153             }
154             }
155 0           return $self;
156             }
157            
158             package WAP::wmls::Url;
159            
160 1     1   7 use base qw(WAP::wmls::OpCode);
  1         1  
  1         690  
161            
162             sub new {
163 0     0     my $proto = shift;
164 0   0       my $class = ref($proto) || $proto;
165 0           my $self = new WAP::wmls::OpCode(@_);
166 0           bless $self, $class;
167 0           return new WAP::wmls::node($self);
168             }
169            
170             package WAP::wmls::AccessDomain;
171            
172 1     1   6 use base qw(WAP::wmls::OpCode);
  1         17  
  1         709  
173            
174             sub new {
175 0     0     my $proto = shift;
176 0   0       my $class = ref($proto) || $proto;
177 0           my $self = new WAP::wmls::OpCode(@_);
178 0           bless $self, $class;
179 0           return new WAP::wmls::node($self);
180             }
181            
182             package WAP::wmls::AccessPath;
183            
184 1     1   5 use base qw(WAP::wmls::OpCode);
  1         1  
  1         491  
185            
186             sub new {
187 0     0     my $proto = shift;
188 0   0       my $class = ref($proto) || $proto;
189 0           my $self = new WAP::wmls::OpCode(@_);
190 0           bless $self, $class;
191 0           return new WAP::wmls::node($self);
192             }
193            
194             package WAP::wmls::MetaName;
195            
196 1     1   4 use base qw(WAP::wmls::OpCode);
  1         12  
  1         526  
197            
198             sub new {
199 0     0     my $proto = shift;
200 0   0       my $class = ref($proto) || $proto;
201 0           my $self = new WAP::wmls::OpCode(@_);
202 0           bless $self, $class;
203 0           return new WAP::wmls::node($self);
204             }
205            
206             package WAP::wmls::MetaHttpEquiv;
207            
208 1     1   5 use base qw(WAP::wmls::OpCode);
  1         1  
  1         731  
209            
210             sub new {
211 0     0     my $proto = shift;
212 0   0       my $class = ref($proto) || $proto;
213 0           my $self = new WAP::wmls::OpCode(@_);
214 0           bless $self, $class;
215 0           return new WAP::wmls::node($self);
216             }
217            
218             package WAP::wmls::MetaUserAgent;
219            
220 1     1   6 use base qw(WAP::wmls::OpCode);
  1         2  
  1         629  
221            
222             sub new {
223 0     0     my $proto = shift;
224 0   0       my $class = ref($proto) || $proto;
225 0           my $self = new WAP::wmls::OpCode(@_);
226 0           bless $self, $class;
227 0           return new WAP::wmls::node($self);
228             }
229            
230             package WAP::wmls::Function;
231            
232 1     1   5 use base qw(WAP::wmls::OpCode);
  1         2  
  1         384  
233            
234 1     1   5 use Carp;
  1         13  
  1         97  
235 1     1   6 use constant UINT8_MAX => 255;
  1         2  
  1         503  
236            
237             sub new {
238 0     0     my $proto = shift;
239 0   0       my $class = ref($proto) || $proto;
240 0           my $parser = shift;
241 0           my $self = new WAP::wmls::OpCode($parser, @_);
242 0           bless $self, $class;
243             # specific
244 0           $self->_SetNbArg($parser);
245 0 0         if (defined $self->{Value}) {
246 0           $self->_CheckBreakContinue($parser, $self->{Value});
247             }
248             else {
249 0           $parser->Warning("function without statement.\n");
250             }
251 0           $parser->YYData->{symbtab_var}->Check();
252 0           return new WAP::wmls::node($self);
253             }
254            
255             sub _SetNbArg {
256 0     0     my $self = shift;
257 0           my ($parser) = @_;
258 0           my $def = $self->{Definition};
259 0 0         if (defined $self->{Param}) {
260 0           my $nbargs = $self->{Param}->{OpCode}->{Index};
261 0 0         if ($nbargs >= UINT8_MAX) {
262 0           $parser->Error("too many function parameter.");
263             }
264             else {
265 0           $def->{NumberOfArguments} = $nbargs;
266             }
267             }
268             else {
269 0           $def->{NumberOfArguments} = 0;
270             }
271 0           return;
272             }
273            
274             sub _CheckBreakContinue {
275 0     0     my $self = shift;
276 0           my ($parser, $block) = @_;
277 0           for (my $node = $block; defined $node; $node = $node->{Next}) {
278 0           my $opcode = $node->{OpCode};
279 0 0 0       if ( $opcode->isa('Jump')
280             and !defined $opcode->{Definition} ) {
281 0           my $type = $opcode->{TypeDef};
282 0 0         if ($type eq 'LABEL_CONTINUE') {
    0          
283 0           $parser->Error("continue without loop.\n");
284             }
285             elsif ($type eq 'LABEL_BREAK') {
286 0           $parser->Error("break without loop.\n");
287             }
288             else {
289 0           croak "INTERNAL_ERROR: _CheckBreakContinue\n";
290             }
291             }
292             }
293 0           return;
294             }
295            
296             package WAP::wmls::Argument;
297            
298 1     1   7 use base qw(WAP::wmls::OpCode);
  1         2  
  1         475  
299            
300             sub new {
301 0     0     my $proto = shift;
302 0   0       my $class = ref($proto) || $proto;
303 0           my $self = new WAP::wmls::OpCode(@_);
304 0           bless $self, $class;
305 0           return new WAP::wmls::node($self);
306             }
307            
308             package WAP::wmls::LoadVar;
309            
310 1     1   4 use base qw(WAP::wmls::OpCode);
  1         2  
  1         510  
311            
312             sub new {
313 0     0     my $proto = shift;
314 0   0       my $class = ref($proto) || $proto;
315 0           my $self = new WAP::wmls::OpCode(@_);
316 0           bless $self, $class;
317 0           return new WAP::wmls::node($self);
318             }
319            
320             package WAP::wmls::StoreVar;
321            
322 1     1   5 use base qw(WAP::wmls::OpCode);
  1         2  
  1         390  
323            
324             sub new {
325 0     0     my $proto = shift;
326 0   0       my $class = ref($proto) || $proto;
327 0           my $self = new WAP::wmls::OpCode(@_);
328 0           bless $self, $class;
329 0           return new WAP::wmls::node($self);
330             }
331            
332             package WAP::wmls::IncrVar;
333            
334 1     1   5 use base qw(WAP::wmls::OpCode);
  1         2  
  1         461  
335            
336             sub new {
337 0     0     my $proto = shift;
338 0   0       my $class = ref($proto) || $proto;
339 0           my $self = new WAP::wmls::OpCode(@_);
340 0           bless $self, $class;
341 0           return new WAP::wmls::node($self);
342             }
343            
344             package WAP::wmls::DecrVar;
345            
346 1     1   5 use base qw(WAP::wmls::OpCode);
  1         13  
  1         455  
347            
348             sub new {
349 0     0     my $proto = shift;
350 0   0       my $class = ref($proto) || $proto;
351 0           my $self = new WAP::wmls::OpCode(@_);
352 0           bless $self, $class;
353 0           return new WAP::wmls::node($self);
354             }
355            
356             package WAP::wmls::AddAsg;
357            
358 1     1   5 use base qw(WAP::wmls::OpCode);
  1         2  
  1         504  
359            
360             sub new {
361 0     0     my $proto = shift;
362 0   0       my $class = ref($proto) || $proto;
363 0           my $self = new WAP::wmls::OpCode(@_);
364 0           bless $self, $class;
365 0           return new WAP::wmls::node($self);
366             }
367            
368             package WAP::wmls::SubAsg;
369            
370 1     1   7 use base qw(WAP::wmls::OpCode);
  1         1  
  1         497  
371            
372             sub new {
373 0     0     my $proto = shift;
374 0   0       my $class = ref($proto) || $proto;
375 0           my $self = new WAP::wmls::OpCode(@_);
376 0           bless $self, $class;
377 0           return new WAP::wmls::node($self);
378             }
379            
380             package WAP::wmls::Label;
381            
382 1     1   5 use base qw(WAP::wmls::OpCode);
  1         2  
  1         581  
383            
384             sub new {
385 0     0     my $proto = shift;
386 0   0       my $class = ref($proto) || $proto;
387 0           my $self = new WAP::wmls::OpCode(@_);
388 0           bless $self, $class;
389 0           return new WAP::wmls::node($self);
390             }
391            
392             package WAP::wmls::Pop;
393            
394 1     1   6 use base qw(WAP::wmls::OpCode);
  1         1  
  1         580  
395            
396             sub new {
397 0     0     my $proto = shift;
398 0   0       my $class = ref($proto) || $proto;
399 0           my $self = new WAP::wmls::OpCode(@_);
400 0           bless $self, $class;
401 0           return new WAP::wmls::node($self);
402             }
403            
404             package WAP::wmls::ToBool;
405            
406 1     1   6 use base qw(WAP::wmls::OpCode);
  1         2  
  1         557  
407            
408             sub new {
409 0     0     my $proto = shift;
410 0   0       my $class = ref($proto) || $proto;
411 0           my $self = new WAP::wmls::OpCode(@_);
412 0           bless $self, $class;
413 0           return new WAP::wmls::node($self);
414             }
415            
416             package WAP::wmls::ScOr;
417            
418 1     1   7 use base qw(WAP::wmls::OpCode);
  1         2  
  1         515  
419            
420             sub new {
421 0     0     my $proto = shift;
422 0   0       my $class = ref($proto) || $proto;
423 0           my $self = new WAP::wmls::OpCode(@_);
424 0           bless $self, $class;
425 0           return new WAP::wmls::node($self);
426             }
427            
428             package WAP::wmls::ScAnd;
429            
430 1     1   6 use base qw(WAP::wmls::OpCode);
  1         1  
  1         440  
431            
432             sub new {
433 0     0     my $proto = shift;
434 0   0       my $class = ref($proto) || $proto;
435 0           my $self = new WAP::wmls::OpCode(@_);
436 0           bless $self, $class;
437 0           return new WAP::wmls::node($self);
438             }
439            
440             package WAP::wmls::Return;
441            
442 1     1   5 use base qw(WAP::wmls::OpCode);
  1         2  
  1         402  
443            
444             sub new {
445 0     0     my $proto = shift;
446 0   0       my $class = ref($proto) || $proto;
447 0           my $self = new WAP::wmls::OpCode(@_);
448 0           bless $self, $class;
449 0           return new WAP::wmls::node($self);
450             }
451            
452             package WAP::wmls::ReturnES;
453            
454 1     1   4 use base qw(WAP::wmls::OpCode);
  1         1  
  1         542  
455            
456             sub new {
457 0     0     my $proto = shift;
458 0   0       my $class = ref($proto) || $proto;
459 0           my $self = new WAP::wmls::OpCode(@_);
460 0           bless $self, $class;
461 0           return new WAP::wmls::node($self);
462             }
463            
464             package WAP::wmls::Call;
465            
466 1     1   5 use base qw(WAP::wmls::OpCode);
  1         1  
  1         433  
467            
468             sub new {
469 0     0     my $proto = shift;
470 0   0       my $class = ref($proto) || $proto;
471 0           my $self = new WAP::wmls::OpCode(@_);
472 0           bless $self, $class;
473 0           return new WAP::wmls::node($self);
474             }
475            
476             package WAP::wmls::CallLib;
477            
478 1     1   5 use base qw(WAP::wmls::OpCode);
  1         1  
  1         546  
479            
480             sub new {
481 0     0     my $proto = shift;
482 0   0       my $class = ref($proto) || $proto;
483 0           my $self = new WAP::wmls::OpCode(@_);
484 0           bless $self, $class;
485 0           return new WAP::wmls::node($self);
486             }
487            
488             package WAP::wmls::CallUrl;
489            
490 1     1   5 use base qw(WAP::wmls::OpCode);
  1         2  
  1         521  
491            
492             sub new {
493 0     0     my $proto = shift;
494 0   0       my $class = ref($proto) || $proto;
495 0           my $self = new WAP::wmls::OpCode(@_);
496 0           bless $self, $class;
497 0           return new WAP::wmls::node($self);
498             }
499            
500             package WAP::wmls::Jump;
501            
502 1     1   6 use base qw(WAP::wmls::OpCode);
  1         8  
  1         587  
503            
504             sub new {
505 0     0     my $proto = shift;
506 0   0       my $class = ref($proto) || $proto;
507 0           my $self = new WAP::wmls::OpCode(@_);
508 0           bless $self, $class;
509 0           return new WAP::wmls::node($self);
510             }
511            
512             package WAP::wmls::FalseJump;
513            
514 1     1   6 use base qw(WAP::wmls::OpCode);
  1         2  
  1         617  
515            
516             sub new {
517 0     0     my $proto = shift;
518 0   0       my $class = ref($proto) || $proto;
519 0           my $self = new WAP::wmls::OpCode(@_);
520 0           bless $self, $class;
521 0           return new WAP::wmls::node($self);
522             }
523            
524             package WAP::wmls::UnaryOp;
525            
526 1     1   6 use base qw(WAP::wmls::OpCode);
  1         1  
  1         423  
527            
528             sub new {
529 0     0     my $proto = shift;
530 0   0       my $class = ref($proto) || $proto;
531 0           my $self = new WAP::wmls::OpCode(@_);
532 0           bless $self, $class;
533 0           return new WAP::wmls::node($self);
534             }
535            
536             package WAP::wmls::BinaryOp;
537            
538 1     1   5 use base qw(WAP::wmls::OpCode);
  1         13  
  1         415  
539            
540             sub new {
541 0     0     my $proto = shift;
542 0   0       my $class = ref($proto) || $proto;
543 0           my $self = new WAP::wmls::OpCode(@_);
544 0           bless $self, $class;
545 0           return new WAP::wmls::node($self);
546             }
547            
548             package WAP::wmls::LoadConst;
549            
550 1     1   5 use base qw(WAP::wmls::OpCode);
  1         2  
  1         2774  
551            
552             sub new {
553 0     0     my $proto = shift;
554 0   0       my $class = ref($proto) || $proto;
555 0           my $self = new WAP::wmls::OpCode(@_);
556 0           bless $self, $class;
557 0           return new WAP::wmls::node($self);
558             }
559            
560             ###############################################################################
561            
562             package WAP::wmls::printVisitor;
563            
564             sub new {
565 0     0     my $proto = shift;
566 0   0       my $class = ref($proto) || $proto;
567 0           my $self = {};
568 0           bless $self, $class;
569 0           $self->{level} = 0;
570 0           return $self;
571             }
572            
573             sub printLabel {
574 0     0     my ($level, $deleted, $label) = @_;
575            
576 0 0         print '~'
577             if ($deleted);
578 0           while ($level--) {
579 0           print "\t";
580             }
581 0           print $label;
582 0           return;
583             }
584            
585             sub printDefn {
586 0     0     my ($def) = @_;
587            
588 0 0         if (defined $def) {
589 0           print " $def->{Symbol}\n";
590             }
591             else {
592 0           print " null\n";
593             }
594 0           return;
595             }
596            
597             sub printOp {
598 0     0     my ($op) = @_;
599            
600 0           print " $op\n";
601 0           return;
602             }
603            
604             sub printConst {
605 0     0     my ($typedef, $value) = @_;
606            
607 0 0         if ($typedef eq 'TYPE_INTEGER') {
    0          
    0          
    0          
    0          
    0          
608 0           print " $value\n";
609             }
610             elsif ($typedef eq 'TYPE_FLOAT') {
611 0           print " $value\n";
612             }
613             elsif ($typedef eq 'TYPE_STRING') {
614 0           print " $value\n";
615             }
616             elsif ($typedef eq 'TYPE_UTF8_STRING') {
617 0           print " $value\n";
618             }
619             elsif ($typedef eq 'TYPE_BOOLEAN') {
620 0 0         if ($value) {
621 0           print " true\n";
622             }
623             else {
624 0           print " false\n";
625             }
626             }
627             elsif ($typedef eq 'TYPE_INVALID') {
628 0           print " INVALID\n";
629             }
630             else {
631 0           print "type incompatible of CONST\n";
632             }
633 0           return;
634             }
635            
636             sub visitUrl {
637 0     0     my $self = shift;
638 0           my ($opcode) = @_;
639 0           printLabel($self->{level}, 0, "URL");
640 0           printDefn($opcode->{Definition});
641 0           $self->{level} ++;
642 0           $opcode->{Value}->visit($self);
643 0           $self->{level} --;
644 0           return;
645             }
646            
647             sub visitAccessDomain {
648 0     0     my $self = shift;
649 0           my ($opcode) = @_;
650 0           printLabel($self->{level}, 0, "ACCESS DOMAIN\n");
651 0           $self->{level} ++;
652 0           $opcode->{Value}->visit($self);
653 0           $self->{level} --;
654 0           return;
655             }
656            
657             sub visitAccessPath {
658 0     0     my $self = shift;
659 0           my ($opcode) = @_;
660 0           printLabel($self->{level}, 0, "ACCESS PATH\n");
661 0           $self->{level} ++;
662 0           $opcode->{Value}->visit($self);
663 0           $self->{level} --;
664 0           return;
665             }
666            
667             sub visitMetaName {
668 0     0     my $self = shift;
669 0           my ($opcode) = @_;
670 0           printLabel($self->{level}, 0, "META NAME\n");
671 0           $self->{level} ++;
672 0           $opcode->{Value}->visit($self);
673 0           $self->{level} --;
674 0           return;
675             }
676            
677             sub visitMetaHttpEquiv {
678 0     0     my $self = shift;
679 0           my ($opcode) = @_;
680 0           printLabel($self->{level}, 0, "META HTTP EQUIV\n");
681 0           $self->{level} ++;
682 0           $opcode->{Value}->visit($self);
683 0           $self->{level} --;
684 0           return;
685             }
686            
687             sub visitMetaUserAgent {
688 0     0     my $self = shift;
689 0           my ($opcode) = @_;
690 0           printLabel($self->{level}, 0, "META USER AGENT\n");
691 0           $self->{level} ++;
692 0           $opcode->{Value}->visit($self);
693 0           $self->{level} --;
694 0           return;
695             }
696            
697             sub visitFunction {
698 0     0     my $self = shift;
699 0           my ($opcode) = @_;
700 0           printf("\n");
701 0           my $def = $opcode->{Definition};
702 0 0         if ($def->{Type} eq 'PRIVATE_FUNC') {
    0          
703 0           printLabel($self->{level}, 0, "FUNCTION");
704             }
705             elsif ($def->{Type} eq 'PUBLIC_FUNC') {
706 0           printLabel($self->{level}, 0, "EXTERN FUNCTION");
707             }
708             else {
709 0           print "Incompatible type of FUNC\n";
710             }
711 0           printDefn($def);
712 0           $self->{level} ++;
713 0 0         $opcode->{Param}->visit($self)
714             if (defined $opcode->{Param});
715 0 0         $opcode->{Value}->visit($self)
716             if (defined $opcode->{Value});
717 0           $self->{level} --;
718 0           return;
719             }
720            
721             sub visitArgument {
722 0     0     my $self = shift;
723 0           my ($opcode) = @_;
724 0           printLabel($self->{level}, 0, "ARG");
725 0           printDefn($opcode->{Definition});
726 0           return;
727             }
728            
729             sub visitLoadVar {
730 0     0     my $self = shift;
731 0           my ($opcode) = @_;
732 0           printLabel($self->{level}, $opcode->{Deleted}, "LOAD_VAR");
733 0           printDefn($opcode->{Definition});
734 0           return;
735             }
736            
737             sub visitStoreVar {
738 0     0     my $self = shift;
739 0           my ($opcode) = @_;
740 0           printLabel($self->{level}, $opcode->{Deleted}, "STORE_VAR");
741 0           printDefn($opcode->{Definition});
742 0           return;
743             }
744            
745             sub visitIncrVar {
746 0     0     my $self = shift;
747 0           my ($opcode) = @_;
748 0           printLabel($self->{level}, $opcode->{Deleted}, "INCR_VAR");
749 0           printDefn($opcode->{Definition});
750 0           return;
751             }
752            
753             sub visitDecrVar {
754 0     0     my $self = shift;
755 0           my ($opcode) = @_;
756 0           printLabel($self->{level}, $opcode->{Deleted}, "DECR_VAR");
757 0           printDefn($opcode->{Definition});
758 0           return;
759             }
760            
761             sub visitAddAsg {
762 0     0     my $self = shift;
763 0           my ($opcode) = @_;
764 0           printLabel($self->{level}, $opcode->{Deleted}, "ADD_ASG");
765 0           printDefn($opcode->{Definition});
766 0           return;
767             }
768            
769             sub visitSubAsg {
770 0     0     my $self = shift;
771 0           my ($opcode) = @_;
772 0           printLabel($self->{level}, $opcode->{Deleted}, "SUB_ASG");
773 0           printDefn($opcode->{Definition});
774 0           return;
775             }
776            
777             sub visitLabel {
778 0     0     my $self = shift;
779 0           my ($opcode) = @_;
780 0           printLabel(0, $opcode->{Deleted}, "LABEL\t");
781 0           printDefn($opcode->{Definition});
782 0           return;
783             }
784            
785             sub visitPop {
786 0     0     my $self = shift;
787 0           my ($opcode) = @_;
788 0           printLabel($self->{level}, $opcode->{Deleted}, "POP\n");
789 0           return;
790             }
791            
792             sub visitToBool {
793 0     0     my $self = shift;
794 0           my ($opcode) = @_;
795 0           printLabel($self->{level}, $opcode->{Deleted}, "TOBOOL\n");
796 0           return;
797             }
798            
799             sub visitScOr {
800 0     0     my $self = shift;
801 0           my ($opcode) = @_;
802 0           printLabel($self->{level}, $opcode->{Deleted}, "SCOR\n");
803 0           return;
804             }
805            
806             sub visitScAnd {
807 0     0     my $self = shift;
808 0           my ($opcode) = @_;
809 0           printLabel($self->{level}, $opcode->{Deleted}, "SCAND\n");
810 0           return;
811             }
812            
813             sub visitReturn {
814 0     0     my $self = shift;
815 0           my ($opcode) = @_;
816 0           printLabel($self->{level}, $opcode->{Deleted}, "RETURN\n");
817 0           return;
818             }
819            
820             sub visitReturnES {
821 0     0     my $self = shift;
822 0           my ($opcode) = @_;
823 0           printLabel($self->{level}, $opcode->{Deleted}, "RETURN_ES\n");
824 0           return;
825             }
826            
827             sub visitCall {
828 0     0     my $self = shift;
829 0           my ($opcode) = @_;
830 0           printLabel($self->{level}, $opcode->{Deleted}, "CALL");
831 0           printDefn($opcode->{Definition});
832 0           return;
833             }
834            
835             sub visitCallLib {
836 0     0     my $self = shift;
837 0           my ($opcode) = @_;
838 0           printLabel($self->{level}, $opcode->{Deleted}, "CALL_LIB");
839 0           printDefn($opcode->{Definition});
840 0           return;
841             }
842            
843             sub visitCallUrl {
844 0     0     my $self = shift;
845 0           my ($opcode) = @_;
846 0           printLabel($self->{level}, $opcode->{Deleted}, "CALL_URL");
847 0           printDefn($opcode->{Definition});
848 0           return;
849             }
850            
851             sub visitJump {
852 0     0     my $self = shift;
853 0           my ($opcode) = @_;
854 0           printLabel($self->{level}, $opcode->{Deleted}, "JUMP\t\t");
855 0           printDefn($opcode->{Definition});
856 0           return;
857             }
858            
859             sub visitFalseJump {
860 0     0     my $self = shift;
861 0           my ($opcode) = @_;
862 0           printLabel($self->{level}, $opcode->{Deleted}, "FALSE_JUMP\t");
863 0           printDefn($opcode->{Definition});
864 0           return;
865             }
866            
867             sub visitUnaryOp {
868 0     0     my $self = shift;
869 0           my ($opcode) = @_;
870 0           printLabel($self->{level}, $opcode->{Deleted}, "UNOP");
871 0           printOp($opcode->{Operator});
872 0           return;
873             }
874            
875             sub visitBinaryOp {
876 0     0     my $self = shift;
877 0           my ($opcode) = @_;
878 0           printLabel($self->{level}, $opcode->{Deleted}, "BINOP");
879 0           printOp($opcode->{Operator});
880 0           return;
881             }
882            
883             sub visitLoadConst {
884 0     0     my $self = shift;
885 0           my ($opcode) = @_;
886 0           printLabel($self->{level}, $opcode->{Deleted}, "LOAD_CONST");
887 0           printConst($opcode->{TypeDef}, $opcode->{Value});
888 0           return;
889             }
890            
891             ###############################################################################
892            
893             package WAP::wmls::defn;
894            
895             sub new {
896 0     0     my $proto = shift;
897 0   0       my $class = ref($proto) || $proto;
898 0           my $self = {};
899 0           bless $self, $class;
900 0           my ($symb, $type) = @_;
901 0           $self->{Symbol} = $symb;
902 0 0         $self->{Type} = $type if (defined $type);
903 0           $self->{ID} = 0xffff;
904 0           $self->{NbUse} = 0;
905 0           return $self;
906             }
907            
908             ###############################################################################
909            
910             package WAP::wmls::SymbTab;
911            
912             sub new {
913 0     0     my $proto = shift;
914 0   0       my $class = ref($proto) || $proto;
915 0           my ($parser) = @_;
916 0           my $self = {};
917 0           bless $self, $class;
918 0           $self->{parser} = $parser;
919 0           $self->{tab} = {};
920 0           return $self;
921             }
922            
923             sub Insert {
924 0     0     my $self = shift;
925 0           my ($symb, $def) = @_;
926 0 0         if (exists $self->{tab}{$symb}) {
927 0           $self->{parser}->Error("Redefinition - $symb.\n");
928             }
929             else {
930 0           $self->{tab}{$symb} = $def;
931             }
932 0           return;
933             }
934            
935             ###############################################################################
936            
937             package WAP::wmls::SymbTabVar;
938            
939 1     1   7 use base qw(WAP::wmls::SymbTab);
  1         2  
  1         4748  
940            
941             sub new {
942 0     0     my $proto = shift;
943 0   0       my $class = ref($proto) || $proto;
944 0           my $self = new WAP::wmls::SymbTab(@_);
945 0           bless $self, $class;
946 0           return $self;
947             }
948            
949             sub InsertLocal {
950 0     0     my $self = shift;
951 0           my ($symb) = @_;
952 0           my $def = new WAP::wmls::defn($symb);
953 0           $def->{NbUse} ++;
954 0           $self->SUPER::Insert($symb, $def);
955 0           return $def;
956             }
957            
958             sub InsertArg {
959 0     0     my $self = shift;
960 0           my ($symb, $num) = @_;
961 0           my $def = new WAP::wmls::defn($symb);
962 0           $def->{ID} = $num;
963 0           $self->SUPER::Insert($symb, $def);
964 0           return $def;
965             }
966            
967             sub Lookup {
968 0     0     my $self = shift;
969 0           my ($symb) = @_;
970 0 0         if (exists $self->{tab}{$symb}) {
971 0           my $def = $self->{tab}{$symb};
972 0           $def->{NbUse} ++;
973 0           return $def;
974             }
975             else {
976 0           $self->{parser}->Error("Variable undefined - $symb.\n");
977 0           return;
978             }
979             }
980            
981             sub Check {
982 0     0     my $self = shift;
983 0           foreach (keys %{$self->{tab}}) {
  0            
984 0           my $def = $self->{tab}{$_};
985 0 0         unless ($def->{NbUse}) {
986 0           $self->{parser}->Warning("Unused variable - $_.\n");
987             }
988             }
989 0           $self->{tab} = {};
990 0           return;
991             }
992            
993             ###############################################################################
994            
995             package WAP::wmls::SymbTabLib;
996            
997 1     1   9 use base qw(WAP::wmls::SymbTab);
  1         3  
  1         871  
998            
999             sub new {
1000 0     0     my $proto = shift;
1001 0   0       my $class = ref($proto) || $proto;
1002 0           my $self = new WAP::wmls::SymbTab(@_);
1003 0           bless $self, $class;
1004 0           return $self;
1005             }
1006            
1007             sub Lookup {
1008 0     0     my $self = shift;
1009 0           my ($library) = @_;
1010 0 0         unless (exists $self->{tab}{$library}) {
1011 0           $self->{parser}->Error("Library unknown - $library.\n");
1012 0           return;
1013             }
1014 0           return 1;
1015             }
1016            
1017             ###############################################################################
1018            
1019             package WAP::wmls::SymbTabFunc;
1020            
1021 1     1   7 use base qw(WAP::wmls::SymbTab);
  1         2  
  1         505  
1022            
1023 1     1   7 use constant UINT8_MAX => 255;
  1         3  
  1         831  
1024            
1025             sub new {
1026 0     0     my $proto = shift;
1027 0   0       my $class = ref($proto) || $proto;
1028 0           my $self = new WAP::wmls::SymbTab(@_);
1029 0           bless $self, $class;
1030 0           $self->{FunctionID} = 0;
1031 0           return $self;
1032             }
1033            
1034             sub InsertLocal {
1035 0     0     my $self = shift;
1036 0           my ($symb, $type) = @_;
1037 0 0 0       if ( $type eq 'PUBLIC_FUNC'
1038             and length $symb > UINT8_MAX ) {
1039 0           $self->{parser}->Error("Too long public function name - $symb.\n");
1040             }
1041 0           my $def = $self->{tab}{$symb};
1042 0 0         if (defined $def) {
1043 0 0         if ($def->{Type} ne 'UNDEF_FUNC') {
1044 0           $self->{parser}->Error("Redefinition - $symb.\n");
1045             }
1046             else {
1047 0           $def->{Type} = $type;
1048             }
1049             }
1050             else {
1051 0           $def = new WAP::wmls::defn($symb, $type);
1052 0           $self->SUPER::Insert($symb, $def);
1053             }
1054 0           $def->{ID} = $self->{FunctionID} ++;
1055 0           return $def;
1056             }
1057            
1058             sub LookupLocal {
1059 0     0     my $self = shift;
1060 0           my ($symb) = @_;
1061 0           my $def = $self->{tab}{$symb};
1062 0 0         unless (defined $def) {
1063 0           $def = new WAP::wmls::defn($symb, 'UNDEF_FUNC');
1064 0           $self->SUPER::Insert($symb, $def);
1065             }
1066 0           return $def;
1067             }
1068            
1069             sub LookupExternal {
1070 0     0     my $self = shift;
1071 0           my ($script, $func, $nbargs) = @_;
1072 0 0         if (length $func > UINT8_MAX) {
1073 0           $self->{parser}->Error("Too long external function name - $func.\n");
1074             }
1075 0 0         if ($nbargs > UINT8_MAX) {
1076 0           $self->{parser}->Error("External function with too many parameter - $func.\n");
1077             }
1078 0           my $symb = $script . '#' . $func;
1079 0           my $def = $self->{tab}{$symb};
1080 0 0         if (defined $def) {
1081 0 0         if ($nbargs != $def->{NumberOfArguments}) {
1082 0           $self->{parser}->Error("Previous call with different argument number - $func.\n");
1083             }
1084             }
1085             else {
1086 0           $def = new WAP::wmls::defn($symb, 'EXTERN_FUNC');
1087 0           $def->{FunctionName} = $func;
1088 0           $def->{NumberOfArguments} = $nbargs;
1089 0           $self->SUPER::Insert($symb, $def);
1090             }
1091 0           return $def;
1092             }
1093            
1094             sub LookupLibrary {
1095 0     0     my $self = shift;
1096 0           my ($library, $func, $nbargs) = @_;
1097 0           my $symb = $library . '.' . $func;
1098 0           my $def = $self->{tab}{$symb};
1099 0 0         if (defined $def) {
1100 0 0         if ($def->{NumberOfArguments} != $nbargs) {
1101 0           $self->{parser}->Error("Wrong argument number for standard function - $func.\n");
1102             }
1103 0           return $def;
1104             }
1105             else {
1106 0           $self->{parser}->Error("Library function unknown - $func.\n");
1107 0           return;
1108             }
1109             }
1110            
1111             sub InsertLibrary {
1112 0     0     my $self = shift;
1113 0           my ($symb, $libId, $id, $nbargs) = @_;
1114 0           my $def = new WAP::wmls::defn($symb, 'STANDARD_FUNC');
1115 0           $def->{LibraryID} = $libId;
1116 0           $def->{ID} = $id;
1117 0           $def->{NumberOfArguments} = $nbargs;
1118 0           $self->SUPER::Insert($symb, $def);
1119 0           return $def;
1120             }
1121            
1122             ###############################################################################
1123            
1124             package WAP::wmls::SymbTabUrl;
1125            
1126 1     1   6 use base qw(WAP::wmls::SymbTab);
  1         2  
  1         582  
1127            
1128             sub new {
1129 0     0     my $proto = shift;
1130 0   0       my $class = ref($proto) || $proto;
1131 0           my $self = new WAP::wmls::SymbTab(@_);
1132 0           bless $self, $class;
1133 0           return $self;
1134             }
1135            
1136             sub Insert {
1137 0     0     my $self = shift;
1138 0           my ($symb) = @_;
1139 0           my $def = new WAP::wmls::defn($symb);
1140 0           $self->SUPER::Insert($symb, $def);
1141 0           return $def;
1142             }
1143            
1144             sub Lookup {
1145 0     0     my $self = shift;
1146 0           my ($script) = @_;
1147 0 0         if (exists $self->{tab}{$script}) {
1148 0           my $def = $self->{tab}{$script};
1149 0           $def->{NbUse} ++;
1150 0           return $def;
1151             }
1152             else {
1153 0           $self->{parser}->Error("ScriptName undefined - $script.\n");
1154 0           return;
1155             }
1156             }
1157            
1158             ###############################################################################
1159            
1160             package WAP::wmls::SymbTabLabel;
1161            
1162 1     1   6 use constant UINT32_MAX => 4294967295;
  1         3  
  1         43  
1163            
1164 1     1   4 use base qw(WAP::wmls::SymbTab);
  1         3  
  1         508  
1165            
1166             sub new {
1167 0     0     my $proto = shift;
1168 0   0       my $class = ref($proto) || $proto;
1169 0           my $self = new WAP::wmls::SymbTab(@_);
1170 0           $self->{idx} = 0;
1171 0           bless $self, $class;
1172 0           return $self;
1173             }
1174            
1175             sub Next {
1176 0     0     my $self = shift;
1177 0           my $symb = sprintf("L%d", $self->{idx}++);
1178 0           my $def = new WAP::wmls::defn($symb);
1179 0           $def->{Index} = UINT32_MAX;
1180 0           $self->SUPER::Insert($symb, $def);
1181 0           return $def;
1182             }
1183            
1184             1;
1185