4
method optimize($ast, *%adverbs) {
5
@!block_stack := [$ast[0]];
6
self.visit_children($ast);
10
method visit_block($block) {
11
@!block_stack.push($block);
13
self.visit_children($block);
20
method find_lex($name) {
21
my int $i := +@!block_stack;
24
my %sym := @!block_stack[$i].symbol($name);
32
method find_sym($name) {
33
my %sym := self.find_lex($name);
34
if !(%sym =:= NQPMu) && nqp::existskey(%sym, 'value') {
38
nqp::die("No compile-time value for $name");
42
method visit_op($op) {
43
sub returns_int($node) {
44
if nqp::objprimspec($node.returns) == 1 {
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)
51
if $typeinfo eq "_i" {
53
} elsif $node.op eq 'chars' || $node.op eq 'ord' || $node.op eq 'elems' {
56
} elsif nqp::istype($node, QAST::IVal) {
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 {
66
self.visit_children($op);
68
my $typeinfo := nqp::chars($op.op) >= 2
69
?? nqp::substr($op.op, nqp::chars($op.op) - 2, 2)
71
my $asm := nqp::substr($op.op, 0, 3);
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";
79
$op.returns(self.find_sym("int"));
81
$op.returns(self.find_sym("num"));
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"))
106
method visit_handle($handle) {
107
self.visit_children($handle, :skip_selectors);
111
method visit_children($node, :$skip_selectors) {
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)
124
self.visit_children($visit);