@@ -2,8 +2,8 @@ class NQP::Optimizer {
2
2
has @ ! block_stack ;
3
3
4
4
method optimize ($ ast , * % adverbs ) {
5
- # @!block_stack := [$ast[0]];
6
- # self.visit_children($ast);
5
+ @ ! block_stack := [$ ast [0 ]];
6
+ self . visit_children($ ast [ 0 ] );
7
7
$ ast ;
8
8
}
9
9
@@ -17,62 +17,104 @@ class NQP::Optimizer {
17
17
$ block ;
18
18
}
19
19
20
- method find_sym (@ name ) {
21
- if + @ name == 1 {
22
- my $ final_name := @ name [0 ];
23
- my $ i := + @ ! block_stack ;
24
- while $ i > 0 {
25
- $ i := $ i - 1 ;
26
- my % sym := @ ! block_stack [$ i ]. symbol($ final_name );
27
- if + % sym {
28
- if nqp ::existskey(% sym , ' value' ) {
29
- say (" found your $ final_name" );
30
- return % sym <value >;
31
- }
32
- else {
33
- nqp ::die(" No compile-time value for $ final_name" );
34
- }
35
- }
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 ;
36
27
}
37
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
+ }
38
40
}
39
41
40
42
method visit_op ($ op ) {
41
43
sub returns_int ($ node ) {
42
44
if nqp ::objprimspec($ node . returns ) == 1 {
43
45
return 1
44
46
}
45
- if nqp ::istype($ node , QAST ::Op) && $ node . op ~~ /_i$ / {
46
- return 1
47
+ if nqp ::istype($ node , QAST ::Op) {
48
+ my $ typeinfo := nqp :: substr ($ node . op, nqp :: chars ($ node . op) - 2 , 2 );
49
+ if $ typeinfo eq " _i" {
50
+ return 1
51
+ } elsif $ node . op eq ' chars' || $ node . op eq ' ord' {
52
+ return 1
53
+ }
47
54
} elsif nqp ::istype($ node , QAST ::IVal) {
48
55
return 1
56
+ } elsif nqp ::istype($ node , QAST ::Var) && $ node . scope eq ' lexical' {
57
+ my % sym ;
58
+ try {
59
+ my % sym := self . find_lex($ node . name );
60
+ CATCH {
61
+ say (" could not find lexpad entry for " ~ $ node . name );
62
+ }
63
+ }
64
+ if nqp ::existskey(% sym , ' type' ) && nqp ::objprimspec(% sym <type >) == 1 {
65
+ say (" var " ~ $ node . name ~ " is native int." );
66
+ return 1
67
+ }
49
68
}
50
69
return 0 ;
51
70
}
52
71
self . visit_children($ op );
53
72
54
- if $ op . op ~~ /^ $ < opt > =(add| sub| mul)_n$ / {
55
- my $ newopn := nqp :: substr ($ op . op, 0 , 3 ) ~ " _i" ;
56
- say ($ op . op ~ " " ~ $ newopn ~ " " ~ $ op . dump);
57
- say (" returns int? " ~ returns_int($ op [0 ]) ~ " \ " ~ returns_int($ op [1 ]));
58
- if returns_int($ op [0 ]) && returns_int($ op [1 ]) {
59
- $ op . name ($ newopn );
60
- $ op . returns (self . find_sym([" int" ]));
61
- say (" transformed!" );
62
- } else {
63
- $ op . returns (self . find_sym([" num" ]));
73
+ my $ typeinfo := nqp :: substr ($ op . op, nqp :: chars ($ op . op) - 2 , 2 );
74
+ my $ asm := nqp :: substr ($ op . op, 0 , 3 );
75
+
76
+ try {
77
+ if $ typeinfo eq ' _n' && ($ asm eq ' add' || $ asm eq ' sub' || $ asm eq ' mul' ) {
78
+ my $ newopn := $ asm ~ " _i" ;
79
+ if returns_int($ op [0 ]) && returns_int($ op [1 ]) {
80
+ my $ newopn := nqp :: substr ($ op . op, 0 , 3 ) ~ " _i" ;
81
+ $ op . name ($ newopn );
82
+ $ op . returns (self . find_sym(" int" ));
83
+ say ($ op . op ~ " " ~ $ newopn ~ " " ~ $ op . dump);
84
+ say (" transformed!" );
85
+ say (" " );
86
+ } else {
87
+ $ op . returns (self . find_sym(" num" ));
88
+ say (returns_int($ op [0 ]) ~ " / " ~ returns_int($ op [1 ]));
89
+ say ($ op . op ~ " " ~ $ newopn ~ " " ~ $ op . dump);
90
+ say (" not transformed!" );
91
+ say (" " );
92
+ }
93
+ } elsif $ typeinfo eq ' _i' {
94
+ $ op . returns (self . find_sym(" num" ));
95
+ } elsif $ typeinfo eq ' _s' {
96
+ $ op . returns (self . find_sym(" str" ));
97
+ } elsif $ op . op eq ' handle' {
98
+ return self . visit_handle($ op );
99
+ } elsif $ op . op eq ' numify' {
100
+ # if we can establish that the argument is a list, we are good
101
+ # to claim it returns an int.
102
+ if nqp ::istype($ op [0 ], QAST ::Var) {
103
+ my $ sigil := nqp :: substr ($ op [0 ]. name , 0 , 1 );
104
+ if $ sigil eq ' @' || $ sigil eq ' %' {
105
+ $ op . returns (self . find_sym(" int" ))
106
+ }
107
+ }
108
+ }
109
+ CATCH {
110
+ say (" too bad, could not do the optimisation" );
111
+ say ($ op . dump);
64
112
}
65
- } elsif $ op . op ~~ /_i$ / {
66
- $ op . returns (self . find_sym([" num" ]));
67
- } elsif $ op . op ~~ /_s$ / {
68
- $ op . returns (self . find_sym([" str" ]));
69
- } elsif $ op . op eq ' handle' {
70
- return self . visit_handle($ op );
71
113
}
72
-
114
+
73
115
$ op ;
74
116
}
75
-
117
+
76
118
method visit_handle ($ handle ) {
77
119
self . visit_children($ handle , : skip_selectors);
78
120
$ handle ;
0 commit comments