~ubuntu-branches/ubuntu/vivid/nqp/vivid-proposed

« back to all changes in this revision

Viewing changes to src/NQP/Optimizer.nqp

  • Committer: Package Import Robot
  • Author(s): Alessandro Ghedini
  • Date: 2013-11-01 12:09:18 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20131101120918-kx51sl0sxl3exsxi
Tags: 2013.10-1
* New upstream release
* Bump versioned (Build-)Depends on parrot
* Update patches
* Install new README.pod
* Fix vcs-field-not-canonical
* Do not install rubyish examples
* Do not Depends on parrot-devel anymore
* Add 07_disable-serialization-tests.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
class NQP::Optimizer {
 
2
    has @!block_stack;
 
3
 
 
4
    method optimize($ast, *%adverbs) {
 
5
        @!block_stack := [$ast[0]];
 
6
        self.visit_children($ast);
 
7
        $ast;
 
8
    }
 
9
 
 
10
    method visit_block($block) {
 
11
        @!block_stack.push($block);
 
12
 
 
13
        self.visit_children($block);
 
14
 
 
15
        @!block_stack.pop();
 
16
 
 
17
        $block;
 
18
    }
 
19
 
 
20
    method find_lex($name) {
 
21
        my int $i := +@!block_stack;
 
22
        while $i > 0 {
 
23
            $i := $i - 1;
 
24
            my %sym := @!block_stack[$i].symbol($name);
 
25
            if +%sym {
 
26
                return %sym;
 
27
            }
 
28
        }
 
29
        NQPMu;
 
30
    }
 
31
 
 
32
    method find_sym($name) {
 
33
        my %sym := self.find_lex($name);
 
34
        if !(%sym =:= NQPMu) && nqp::existskey(%sym, 'value') {
 
35
            return %sym<value>;
 
36
        }
 
37
        else {
 
38
            nqp::die("No compile-time value for $name");
 
39
        }
 
40
    }
 
41
 
 
42
    method visit_op($op) {
 
43
        sub returns_int($node) {
 
44
            if nqp::objprimspec($node.returns) == 1 {
 
45
                return 1
 
46
            }
 
47
            if nqp::istype($node, QAST::Op) {
 
48
                my $typeinfo := nqp::chars($node.op) >= 2
 
49
                                ?? nqp::substr($node.op, nqp::chars($node.op) - 2, 2)
 
50
                                !! "";
 
51
                if $typeinfo eq "_i" {
 
52
                    return 1
 
53
                } elsif $node.op eq 'chars' || $node.op eq 'ord' || $node.op eq 'elems' {
 
54
                    return 1
 
55
                }
 
56
            } elsif nqp::istype($node, QAST::IVal) {
 
57
                return 1
 
58
            } elsif nqp::istype($node, QAST::Var) && $node.scope eq 'lexical' {
 
59
                my %sym := self.find_lex($node.name);
 
60
                if nqp::existskey(%sym, 'type') && nqp::objprimspec(%sym<type>) == 1 {
 
61
                    return 1
 
62
                }
 
63
            }
 
64
            return 0;
 
65
        }
 
66
        self.visit_children($op);
 
67
 
 
68
        my $typeinfo := nqp::chars($op.op) >= 2
 
69
                        ?? nqp::substr($op.op, nqp::chars($op.op) - 2, 2)
 
70
                        !! "";
 
71
        my $asm := nqp::substr($op.op, 0, 3);
 
72
 
 
73
        try {
 
74
            if $typeinfo eq '_n' && ($asm eq 'add' || $asm eq 'sub' || $asm eq 'mul') {
 
75
                my $newopn := $asm ~ "_i";
 
76
                if returns_int($op[0]) && returns_int($op[1]) {
 
77
                    my $newopn := $asm ~ "_i";
 
78
                    $op.op($newopn);
 
79
                    $op.returns(self.find_sym("int"));
 
80
                } else {
 
81
                    $op.returns(self.find_sym("num"));
 
82
                }
 
83
            } elsif $typeinfo eq '_i' {
 
84
                $op.returns(self.find_sym("num"));
 
85
            } elsif $typeinfo eq '_s' {
 
86
                $op.returns(self.find_sym("str"));
 
87
            } elsif $op.op eq 'handle' {
 
88
                return self.visit_handle($op);
 
89
            } elsif $op.op eq 'numify' {
 
90
                # if we can establish that the argument is a list, we are good
 
91
                # to claim it returns an int.
 
92
                if nqp::istype($op[0], QAST::Var) {
 
93
                    my $sigil := nqp::substr($op[0].name, 0, 1);
 
94
                    if $sigil eq '@' || $sigil eq '%' {
 
95
                        $op.returns(self.find_sym("int"))
 
96
                    }
 
97
                }
 
98
            }
 
99
            CATCH {
 
100
            }
 
101
        }
 
102
 
 
103
        $op;
 
104
    }
 
105
 
 
106
    method visit_handle($handle) {
 
107
        self.visit_children($handle, :skip_selectors);
 
108
        $handle;
 
109
    }
 
110
 
 
111
    method visit_children($node, :$skip_selectors) {
 
112
        my int $i := 0;
 
113
        unless nqp::isstr($node) {
 
114
            while $i < +@($node) {
 
115
                unless $skip_selectors && $i % 2 {
 
116
                    my $visit := $node[$i];
 
117
                    if nqp::istype($visit, QAST::Op) {
 
118
                        $node[$i] := self.visit_op($visit)
 
119
                    } elsif nqp::istype($visit, QAST::Block) {
 
120
                        $node[$i] := self.visit_block($visit)
 
121
                    } elsif nqp::istype($visit, QAST::Want) {
 
122
                        self.visit_children($visit, :skip_selectors)
 
123
                    } else {
 
124
                        self.visit_children($visit);
 
125
                    }
 
126
                }
 
127
                $i := $i + 1;
 
128
            }
 
129
        }
 
130
    }
 
131
}