Skip to content

Commit

Permalink
Removed the concept of "Blockish".
Browse files Browse the repository at this point in the history
- Now every node that should have a block has a SAST::Block
- Stop auto optimizing empty SAST:Block to a SAST::Nop
- SAST::If now hides its `else` from the composer and walks them top
  down (manually)

The end result is that we can properly inline things like:

    my Pkg $nc = given $*os {
        when Debian { 'netcat' }
        when RHEL   { 'nc' }
        default     { 'nc' }
    };

To just (in the shell):

    nc=netcat
  • Loading branch information
LLFourn committed Mar 17, 2017
1 parent 045d00f commit 86afea0
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 42 deletions.
2 changes: 1 addition & 1 deletion lib/Spit/Parser/Actions.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ method declaration:sym<class> ($/){

method declare-class-params ($/) {
for $*CLASS.class.^placeholder-params -> $type {
$*CURPAD.declare: SAST::ClassDeclaration.new(class => $type,block => SAST::Nop.new);
$*CURPAD.declare: SAST::ClassDeclaration.new(class => $type);
}
}

Expand Down
36 changes: 22 additions & 14 deletions lib/Spit/SAST.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,6 @@ role SAST::OSMutant {
method mutate-for-os($os) {...}
}

subset Blockish of SAST where SAST::Block|SAST::Nop;

class SAST::Children does SAST {

method children { Empty }
Expand Down Expand Up @@ -304,7 +302,7 @@ class SAST::MutableChildren is SAST::Children {
}

class SAST::CompUnit is SAST::Children {
has Blockish:D $.block is required is rw;
has SAST::Block:D $.block is required is rw;
has $.depends-on is rw; # A Spit::DependencyList
has @.phasers;
has @.exported;
Expand Down Expand Up @@ -424,6 +422,7 @@ class SAST::MaybeReplace is SAST::VarDecl {
method replace-with {
given $.assign {
when *.compile-time.defined { $_ }
when { .compile-time ~~ Spit::Type } { $_ }
when SAST::Var|SAST::Param|SAST::Invocant { $_ }
default { Nil }
}
Expand Down Expand Up @@ -498,8 +497,13 @@ class SAST::Block is SAST::MutableChildren does SAST::Dependable {
@.children.reverse.first({ $_ !~~ SAST::PhaserBlock });
}

method one-stmt {
@.children[0] if @.children == 1;
method one-stmt is rw {
if @.children.grep({$_ !~~ SAST::PhaserBlock}) == 1 {
given self.last-stmt {
when SAST::Return { .val }
default { $_ }
}
}
}

method type {
Expand Down Expand Up @@ -955,7 +959,7 @@ class SAST::Signature is SAST::Children {

class SAST::ClassDeclaration does SAST::Declarable is SAST::Children {
has Spit::Type $.class is required;
has Blockish $.block is rw;
has SAST::Block $.block is rw;

method symbol-type { CLASS }
method name { self.class.^name }
Expand Down Expand Up @@ -1260,7 +1264,7 @@ sub generate-topic-var(:$var! is rw,:$cond! is rw,:@blocks!) {

class SAST::If is SAST::Children is rw {
has SAST:D $.cond is required is rw;
has Blockish $.then is rw;
has SAST::Block $.then is rw;
has SAST $.else is rw;
has SAST::VarDecl $.topic-var;
has $.when;
Expand All @@ -1278,13 +1282,17 @@ class SAST::If is SAST::Children is rw {
self;
}

method children { $!cond,$!then,($!else // Empty),($!topic-var // Empty) }
method children {
$!cond,$!then,($!topic-var // Empty),
# Hide else from composer initially. Ifs need to be walked from top to bottom.
($!else // Empty if $.stage3-done)
}
method type { derive-common-parent($!then.type, ($!else.type if $!else)) }
}

class SAST::While is SAST::Children {
has SAST:D $.cond is required is rw;
has Blockish $.block is rw;
has SAST::Block $.block is rw;
has $.until;
has SAST::VarDecl $.topic-var;

Expand All @@ -1300,7 +1308,7 @@ class SAST::While is SAST::Children {

class SAST::Given is SAST::Children is rw {
has SAST:D $.given is required;
has Blockish:D $.block is required;
has SAST::Block:D $.block is required;
has SAST::VarDecl $.topic-var;

method stage2($ctx) {
Expand All @@ -1317,7 +1325,7 @@ class SAST::Given is SAST::Children is rw {
}

class SAST::For is SAST::Children {
has Blockish $.block is rw;
has SAST::Block $.block is rw;
has SAST:D $.list is required;
has SAST::VarDecl $.iter-var;

Expand Down Expand Up @@ -1395,10 +1403,10 @@ class SAST::Blessed is SAST::MutableChildren is SAST::Type {
if self.class-type.^lookup-by-str($str) -> $lookup {
SAST::Type.new(class-type => $lookup, match => self[0].match).do-stage2($ctx);
} else {
SX.new(message => "'$str' is not part of the {self.class-type.name}").throw;
self.make-new(SX, message => "'$str' is not part of the {self.class-type.name}").throw;
}
} else {
SX.new(message => "Can't lookup a {self.class-type.name} with a runtime value").throw;
self.make-new(SX, message => message => "Can't lookup a {self.class-type.name} with a runtime value").throw;
}
} else {
self[0] .= do-stage2(self.type,:desc("didn't match primitive"));
Expand Down Expand Up @@ -1540,7 +1548,7 @@ class SAST::FileContent is SAST::Children {
}

class SAST::Quietly is SAST::Children {
has Blockish:D $.block is required;
has SAST::Block:D $.block is required;
has SAST $.null is rw;

method stage2($ctx) {
Expand Down
30 changes: 12 additions & 18 deletions lib/Spit/Sh/Compiler.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ multi method node(SAST::CompUnit:D $*CU) {
|self.node($*CU.block,|%_).grep(*.defined);
}

method compile-nodes(@sast,:$one-line,:$indent) {
method compile-nodes(@sast,:$one-line,:$indent,:$no-empty) {
my ShellElement:D @chunk;
my $*indent = CALLERS::<$*indent> || 0;
$*indent++ if $indent;
Expand All @@ -212,9 +212,9 @@ method compile-nodes(@sast,:$one-line,:$indent) {
@chunk.append: @node;
}
}
# unless @chunk {
# @chunk.append: $*pad,': nop';
# }
if $no-empty and not @chunk {
@chunk.push("$*pad:");
}
return @chunk;
}

Expand Down Expand Up @@ -272,8 +272,8 @@ method try-case($if is copy) {
my $i = 0;
while $if and $can {
my ($topic,$pattern);
if $if ~~ SAST::Block {
@res.append: "\n$*pad *) ", |self.node($if,:inline,:one-line),';;';
if $if !~~ SAST::If {
@res.append: "\n$*pad *) ", |self.node($if,:one-line),';;';
$if = Nil;
} elsif (
(my \cond = $if.cond) ~~ SAST::Cmp && cond.sym eq 'eq'
Expand Down Expand Up @@ -346,8 +346,8 @@ multi method node(SAST::If:D $_,:$else) {
|self.node(.then,:indent,:no-empty),
|(with .else {
when SAST::Nop { Empty }
when SAST::Block { "\n{$*pad}else\n",|self.node($_,:indent) }
default { "\n{$*pad}",|self.node($_,:else) }
when SAST::If { "\n{$*pad}",|self.node($_,:else) }
when SAST::Block { "\n{$*pad}else\n",|self.node($_,:indent,:no-empty) }
} elsif .type ~~ tBool() {
# if false; then false; fi; actually exits 0 (?!)
# So we have to make sure it exits 1 if the cond is false
Expand Down Expand Up @@ -391,9 +391,9 @@ multi method node(SAST::Ternary:D $_,:$tight) {
('; }' if $tight);
}

multi method node(SAST::Block:D $block,:$indent is copy,:$curlies,:$one-line) {
multi method node(SAST::Block:D $block,:$indent is copy,:$curlies,:$one-line,:$no-empty) {
$indent ||= True if $curlies;
my @compiled = self.compile-nodes($block.children,:$indent,:$one-line);
my @compiled = self.compile-nodes($block.children,:$indent,:$one-line,:$no-empty);
if $curlies {
self.maybe-oneline-block(@compiled);
} else {
Expand Down Expand Up @@ -526,13 +526,7 @@ multi method node(SAST:D $_) {
': ',|self.arg($_);
}

multi method node(SAST::Nop:D $_,:$indent,:$no-empty) {
if $no-empty {
$*pad,' :nop';
} else {
Empty
}
}
multi method node(SAST::Nop:D $_) { Empty }

multi method node(SAST::Quietly:D $_) {
|self.node(.block,:curlies),' 2>',('&' if .null.type ~~ tFD()),self.arg(.null);
Expand Down Expand Up @@ -701,7 +695,7 @@ multi method arg(SAST::Negative:D $_) {

multi method arg(SAST::Block:D $_) {
if .one-stmt -> $return {
self.arg($return.val);
self.arg($return);
} else {
cs self.node($_,:one-line);
}
Expand Down
24 changes: 16 additions & 8 deletions lib/Spit/Sh/Composer.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,19 @@ multi method walk(SAST::ClassDeclaration:D $THIS is rw) {
$THIS .= stage3-node(SAST::Nop);
}

multi method walk(SAST::Block:D $THIS is rw) {
if $THIS.children == 0 || $THIS.children.all ~~ SAST::Nop {
$THIS .= stage3-node(SAST::Nop);
} elsif $THIS.children === 1 {

multi method reduce-block(SAST::Block:D $block) {
if $block.children == 0 || $block.children.all ~~ SAST::Nop {
$block.stage3-node(SAST::Nop);
} elsif $block.one-stmt -> $one-stmt {
$one-stmt;
} else {
$block;
}
}

multi method reduce-block(SAST:D $non-block) { $non-block }

multi method walk(SAST::While:D $THIS is rw) {
with $THIS.cond.compile-time -> $cond {
if not $cond {
Expand All @@ -86,17 +91,20 @@ multi method walk(SAST::While:D $THIS is rw) {
}
}

multi method walk(SAST::If:D $THIS is rw) {
multi method walk(SAST::If:D $THIS is rw,:$sub-if) {
with $THIS.cond.compile-time -> $cond {
if ?$cond {
$THIS .= then;
$THIS = $sub-if ?? $THIS.then !! self.reduce-block($THIS.then);
} else {
if $THIS.else -> $else {
if $THIS.else <-> $else {
$THIS = $else;
self.walk($THIS);
} else {
$THIS .= stage3-node(SAST::Nop);
}
}
} else {
$THIS.else andthen self.walk($_,:sub-if);
}
}

Expand Down Expand Up @@ -432,7 +440,7 @@ multi method walk(SAST::Call:D $THIS is rw, $accept = True) {
if $THIS.declaration.chosen-block -> $block {
if $block ~~ SAST::Block and not $block.ann<cant-inline> {
# only inline routines with one child for now
if $block.children == 1 && ($block.returns.?val || $block.last-stmt) <-> $last-stmt {
if $block.one-stmt <-> $last-stmt {
if self.inline-call($THIS,$last-stmt) -> $replacement {
if $replacement ~~ $accept {
$THIS = $replacement;
Expand Down
11 changes: 10 additions & 1 deletion t/inlining.t
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
use Test;
use Spit::Compile;

plan 1;
plan 2;

ok compile(name => "Cmd || Cmd",Q{ my $a = Cmd<printf> || Cmd<echo> || Cmd<true> }).
contains('exists printf'&'exists echo'), "Cmd junction always looks like exists cmd ||";

ok compile(name => "given inline", Q{
my Pkg $nc = given $*os {
when Debian { 'netcat' }
when RHEL { 'nc' }
default { 'nc' }
};
note $nc;
}).contains('nc=netcat'), 'given block completely inline away';

0 comments on commit 86afea0

Please sign in to comment.