Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
working build, lots of debug output, more intelligence.
  • Loading branch information
timo committed Aug 20, 2013
1 parent 459e172 commit ba977c2
Showing 1 changed file with 80 additions and 38 deletions.
118 changes: 80 additions & 38 deletions src/NQP/Optimizer.nqp
Expand Up @@ -2,8 +2,8 @@ class NQP::Optimizer {
has @!block_stack;

method optimize($ast, *%adverbs) {
#@!block_stack := [$ast[0]];
#self.visit_children($ast);
@!block_stack := [$ast[0]];
self.visit_children($ast[0]);
$ast;
}

Expand All @@ -17,62 +17,104 @@ class NQP::Optimizer {
$block;
}

method find_sym(@name) {
if +@name == 1 {
my $final_name := @name[0];
my $i := +@!block_stack;
while $i > 0 {
$i := $i - 1;
my %sym := @!block_stack[$i].symbol($final_name);
if +%sym {
if nqp::existskey(%sym, 'value') {
say("found your $final_name");
return %sym<value>;
}
else {
nqp::die("No compile-time value for $final_name");
}
}
method find_lex($name) {
my int $i := +@!block_stack;
while $i > 0 {
$i := $i - 1;
my %sym := @!block_stack[$i].symbol($name);
if +%sym {
return %sym;
}
}
NQPMu;
}

method find_sym($name) {
my %sym := self.find_lex($name);
if !(%sym =:= NQPMu) && nqp::existskey(%sym, 'value') {
return %sym<value>;
}
else {
nqp::die("No compile-time value for $name");
}
}

method visit_op($op) {
sub returns_int($node) {
if nqp::objprimspec($node.returns) == 1 {
return 1
}
if nqp::istype($node, QAST::Op) && $node.op ~~ /_i$/ {
return 1
if nqp::istype($node, QAST::Op) {
my $typeinfo := nqp::substr($node.op, nqp::chars($node.op) - 2, 2);
if $typeinfo eq "_i" {
return 1
} elsif $node.op eq 'chars' || $node.op eq 'ord' {
return 1
}
} elsif nqp::istype($node, QAST::IVal) {
return 1
} elsif nqp::istype($node, QAST::Var) && $node.scope eq 'lexical' {
my %sym;
try {
my %sym := self.find_lex($node.name);
CATCH {
say("could not find lexpad entry for " ~ $node.name);
}
}
if nqp::existskey(%sym, 'type') && nqp::objprimspec(%sym<type>) == 1 {
say("var " ~ $node.name ~ " is native int.");
return 1
}
}
return 0;
}
self.visit_children($op);

if $op.op ~~ /^$<opt>=(add|sub|mul)_n$/ {
my $newopn := nqp::substr($op.op, 0, 3) ~ "_i";
say($op.op ~ " " ~ $newopn ~ " " ~ $op.dump);
say("returns int? " ~ returns_int($op[0]) ~ " \ " ~ returns_int($op[1]));
if returns_int($op[0]) && returns_int($op[1]) {
$op.name($newopn);
$op.returns(self.find_sym(["int"]));
say("transformed!");
} else {
$op.returns(self.find_sym(["num"]));
my $typeinfo := nqp::substr($op.op, nqp::chars($op.op) - 2, 2);
my $asm := nqp::substr($op.op, 0, 3);

try {
if $typeinfo eq '_n' && ($asm eq 'add' || $asm eq 'sub' || $asm eq 'mul') {
my $newopn := $asm ~ "_i";
if returns_int($op[0]) && returns_int($op[1]) {
my $newopn := nqp::substr($op.op, 0, 3) ~ "_i";
$op.name($newopn);
$op.returns(self.find_sym("int"));
say($op.op ~ " " ~ $newopn ~ " " ~ $op.dump);
say("transformed!");
say("");
} else {
$op.returns(self.find_sym("num"));
say(returns_int($op[0]) ~ " / " ~ returns_int($op[1]));
say($op.op ~ " " ~ $newopn ~ " " ~ $op.dump);
say("not transformed!");
say("");
}
} elsif $typeinfo eq '_i' {
$op.returns(self.find_sym("num"));
} elsif $typeinfo eq '_s' {
$op.returns(self.find_sym("str"));
} elsif $op.op eq 'handle' {
return self.visit_handle($op);
} elsif $op.op eq 'numify' {
# if we can establish that the argument is a list, we are good
# to claim it returns an int.
if nqp::istype($op[0], QAST::Var) {
my $sigil := nqp::substr($op[0].name, 0, 1);
if $sigil eq '@' || $sigil eq '%' {
$op.returns(self.find_sym("int"))
}
}
}
CATCH {
say("too bad, could not do the optimisation");
say($op.dump);
}
} elsif $op.op ~~ /_i$/ {
$op.returns(self.find_sym(["num"]));
} elsif $op.op ~~ /_s$/ {
$op.returns(self.find_sym(["str"]));
} elsif $op.op eq 'handle' {
return self.visit_handle($op);
}

$op;
}

method visit_handle($handle) {
self.visit_children($handle, :skip_selectors);
$handle;
Expand Down

0 comments on commit ba977c2

Please sign in to comment.