Skip to content

Commit

Permalink
[truffle] Refactor QAST::Op handling
Browse files Browse the repository at this point in the history
Instead of an if chain keep a hash of callbacks.
The design is borrowed from the JS backend.
  • Loading branch information
pmurias committed Jun 22, 2018
1 parent 5fe4c8d commit 85a2b55
Showing 1 changed file with 92 additions and 19 deletions.
111 changes: 92 additions & 19 deletions nqp-truffle.nqp
@@ -1,5 +1,86 @@
class QAST::TruffleCompiler {
my $T_OBJ := 0;
my $T_INT := 1;
my $T_NUM := 2;
my $T_STR := 3;

class QAST::OperationsTruffle {
my %ops;
my %hll_ops;

my %inlinable;

sub add_op($op, $cb, :$inlinable = 1, :$hll) {
if $hll {
%hll_ops{$hll} := nqp::hash() unless nqp::existskey(%hll_ops, $hll);
%hll_ops{$hll}{$op} := $cb;
} else {
%ops{$op} := $cb;
}
%inlinable{$op} := $inlinable;
}

sub add_simple_op($op, $return_type, @argument_types, :$side_effects, :$inlinable = 1, :$decont, :$hll) {
my @decont;
if nqp::islist($decont) {
for $decont -> $index {
@decont[$index] := 1;
}
}
elsif nqp::defined($decont) {
@decont[$decont] := 1;
}


add_op($op, sub ($comp, $node, :$want) {
if $node.list > @argument_types {
nqp::die("{+$node.list} arguments for {$node.op}, the maximum is {+@argument_types}");
}

my @ret := [$op];

my int $i := 0;
for $node.list -> $arg {
my $tree := $comp.as_truffle($arg, :want(@argument_types[$i]));
nqp::push(@ret, @decont[$i] ?? ['decont', $tree] !! $tree);
$i := $i + 1;
}

@ret;
}, :$inlinable, :$hll);
}

add_simple_op('say', $T_STR, [$T_STR], :side_effects);
add_simple_op('print', $T_STR, [$T_STR], :side_effects);

# explicit takeclosure is used by the JVM backend we no-op it.
add_op('takeclosure', sub ($comp, $node, :$want) {
$comp.as_truffle($node[0], :want($want));
});

# TODO :$want
add_op('call', :!inlinable, sub ($comp, $node, :$want) {
my $ret := ['call'];
for $node.list -> $child {
nqp::push($ret, $comp.as_truffle($child));
}
$ret;
});

method compile_op($comp, $op, $hll, :$want) {
my str $name := $op.op;
if nqp::existskey(%hll_ops, $hll) && nqp::existskey(%hll_ops{$hll}, $name) {
%hll_ops{$hll}{$name}($comp, $op, :$want);
}
elsif nqp::existskey(%ops, $name) {
%ops{$name}($comp, $op, :$want);
}
else {
$comp.NYI("unimplemented QAST::Op {$op.op}");
}
}
}

class QAST::TruffleCompiler {
method sexpr($thing) {
if nqp::islist($thing) {
my @ret;
Expand All @@ -13,17 +94,23 @@ class QAST::TruffleCompiler {
}

method run(QAST::CompUnit $cu) {
my $compiled := self.as_truffle($cu, :want(0));
my $compiled := self.as_truffle($cu, :want($T_OBJ));

say(self.sexpr($compiled));
nqp::runtruffle($compiled);
}

proto method as_truffle($node, :$want) {
{*}
}

multi method as_truffle(QAST::CompUnit $cu, :$want) {
self.as_truffle($cu[0][3]);
multi method as_truffle(QAST::CompUnit $node, :$want) {
my $*HLL := '';
if $node.hll {
$*HLL := $node.hll;
}

self.as_truffle($node[0][3]);
}

multi method as_truffle(QAST::Stmts $node, :$want) {
Expand All @@ -47,21 +134,7 @@ class QAST::TruffleCompiler {
}

multi method as_truffle(QAST::Op $node, :$want) {
if $node.op eq 'say' {
['say', self.as_truffle($node[0])];
} elsif $node.op eq 'print' {
['print', self.as_truffle($node[0])];
} elsif $node.op eq 'call' {
my $ret := ['call'];
for $node.list -> $child {
nqp::push($ret, self.as_truffle($child));
}
$ret;
} elsif $node.op eq 'takeclosure' {
return self.as_truffle($node[0], :$want);
} else {
nqp::die('NYI op: ' ~ $node.op);
}
QAST::OperationsTruffle.compile_op(self, $node, $*HLL, :$want);
}

multi method as_truffle(QAST::Node $node, :$want) {
Expand Down

0 comments on commit 85a2b55

Please sign in to comment.