Skip to content

Commit

Permalink
[js] When building Chunks create less empty and one element arrays.
Browse files Browse the repository at this point in the history
  • Loading branch information
pmurias committed Nov 27, 2016
1 parent 1212b7d commit 3126d69
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 52 deletions.
61 changes: 41 additions & 20 deletions src/vm/js/Chunk.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Chunk does Joinable {
has $!node; # a QAST::Node that contains info for source maps
has $!setup; # stuff that needs to be executed before the value of $!expr can be used, this contains strings and Chunks.

method new($type, $expr, $setup = [], :$node) {
method new($type, $expr, $setup = nqp::null(), :$node) {
my $obj := nqp::create(self);
$obj.BUILD($type, $expr, $setup, :$node);
$obj
Expand All @@ -42,24 +42,38 @@ class Chunk does Joinable {
}

method collect(@strs, :$escape) {
for $!setup -> $part {
if nqp::isstr($part) {
nqp::push_s(@strs, $escape ?? nqp::escape($part) !! $part);
}
else {
$part.collect(@strs, :$escape);
if nqp::isnull($!setup) {
}
elsif nqp::istype($!setup, Chunk) {
$!setup.collect(@strs, :$escape);
}
else {
for $!setup -> $part {
if nqp::isstr($part) {
nqp::push_s(@strs, $escape ?? nqp::escape($part) !! $part);
}
else {
$part.collect(@strs, :$escape);
}
}
}
}

method with_source_map_info() {
my @parts;
for $!setup -> $part {
if nqp::isstr($part) {
nqp::push(@parts,quote_string($part, :json));
}
else {
nqp::push(@parts,$part.with_source_map_info);
if nqp::isnull($!setup) {
}
elsif nqp::istype($!setup, Chunk) {
nqp::push(@parts, $!setup.with_source_map_info);
}
else {
for $!setup -> $part {
if nqp::isstr($part) {
nqp::push(@parts,quote_string($part, :json));
}
else {
nqp::push(@parts,$part.with_source_map_info);
}
}
}
my $parts := '[' ~ nqp::join(',', @parts) ~ ']';
Expand All @@ -75,13 +89,20 @@ class Chunk does Joinable {

method source_map_debug() {
my $js := '';
for $!setup -> $part {
if nqp::isstr($part) {
$js := $js ~ $part;
}
else {
$js := $js ~ $part.source_map_debug;
}
if nqp::isnull($!setup) {
}
elsif nqp::istype($!setup, Chunk) {
$js := $js ~ $!setup.source_map_debug;
}
else {
for $!setup -> $part {
if nqp::isstr($part) {
$js := $js ~ $part;
}
else {
$js := $js ~ $part.source_map_debug;
}
}
}

if nqp::defined($!node) && $!node.node {
Expand Down
57 changes: 30 additions & 27 deletions src/vm/js/Compiler.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -523,10 +523,10 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
if $desired == $T_NUM {
if $got == $T_INT {
# we store both as a javascript number, and 32bit integers fit into doubles
return Chunk.new($T_NUM, $chunk.expr, [$chunk]);
return Chunk.new($T_NUM, $chunk.expr, $chunk);
}
if $got == $T_BOOL {
return Chunk.new($T_NUM, "({$chunk.expr} ? 1 : 0)", [$chunk]);
return Chunk.new($T_NUM, "({$chunk.expr} ? 1 : 0)", $chunk);
}
if $got == $T_STR {
my $tmp := $*BLOCK.add_tmp();
Expand All @@ -536,68 +536,68 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {

if $desired == $T_INT {
if $got == $T_STR {
return Chunk.new($T_INT, "parseInt({$chunk.expr})", [$chunk]);
return Chunk.new($T_INT, "parseInt({$chunk.expr})", $chunk);
}
if $got == $T_NUM {
return Chunk.new($T_INT, "({$chunk.expr}|0)", [$chunk]);
return Chunk.new($T_INT, "({$chunk.expr}|0)", $chunk);
}
if $got == $T_BOOL {
return Chunk.new($T_INT, "({$chunk.expr} ? 1 : 0)", [$chunk]);
return Chunk.new($T_INT, "({$chunk.expr} ? 1 : 0)", $chunk);
}
}

if $got == $T_OBJ {
if $desired == $T_BOOL {
return Chunk.new($desired, "{$chunk.expr}.\$\$decont($*CTX).\$\$toBool($*CTX)", [$chunk]);
return Chunk.new($desired, "{$chunk.expr}.\$\$decont($*CTX).\$\$toBool($*CTX)", $chunk);
}
my %convert;
%convert{$T_STR} := 'toStr';
%convert{$T_NUM} := 'toNum';
%convert{$T_INT} := 'toInt';
return Chunk.new($desired, 'nqp.' ~ %convert{$desired} ~ '(' ~ $chunk.expr ~ ", {$*CTX})", [$chunk]);
return Chunk.new($desired, 'nqp.' ~ %convert{$desired} ~ '(' ~ $chunk.expr ~ ", {$*CTX})", $chunk);
}

if $desired == $T_STR {
if $got == $T_INT || $got == $T_NUM {
return Chunk.new($T_STR, $chunk.expr ~ '.toString()', [$chunk]);
return Chunk.new($T_STR, $chunk.expr ~ '.toString()', $chunk);
}
if $got == $T_BOOL {
return Chunk.new($T_STR, "({$chunk.expr} ? '1' : '0')", [$chunk]);
return Chunk.new($T_STR, "({$chunk.expr} ? '1' : '0')", $chunk);
}
}

if $desired == $T_OBJ {
if $got == $T_BOOL {
$chunk := Chunk.new($T_INT, "({$chunk.expr} ? 1 : 0)", [$chunk]);
$chunk := Chunk.new($T_INT, "({$chunk.expr} ? 1 : 0)", $chunk);
$got := $T_INT;
}
elsif $got == $T_VOID {
# TODO think what's the correct thing here
return Chunk.new($T_OBJ, "nqp.Null", [$chunk]);
return Chunk.new($T_OBJ, "nqp.Null", $chunk);
}

if $*HLL eq 'nqp' {
if $got == $T_NUM || $got == $T_STR {
return $chunk;
}
elsif $got == $T_INT {
return Chunk.new($T_OBJ, "new nqp.NQPInt({$chunk.expr})", [$chunk]);
return Chunk.new($T_OBJ, "new nqp.NQPInt({$chunk.expr})", $chunk);
}
}
else {
my %convert;
%convert{$T_INT} := 'intToObj';
%convert{$T_NUM} := 'numToObj';
%convert{$T_STR} := 'strToObj';
return Chunk.new($T_OBJ, "nqp.{%convert{$got}}({quote_string($*HLL)}, {$chunk.expr})", [$chunk]);
return Chunk.new($T_OBJ, "nqp.{%convert{$got}}({quote_string($*HLL)}, {$chunk.expr})", $chunk);
}
}

if $desired == $T_BOOL {
if $got == $T_INT || $got == $T_NUM {
return Chunk.new($T_BOOL, $chunk.expr, [$chunk]);
return Chunk.new($T_BOOL, $chunk.expr, $chunk);
} elsif $got == $T_STR {
return Chunk.new($T_BOOL, "({$chunk.expr} && {$chunk.expr} !== nqp.null_s)", [$chunk]);
return Chunk.new($T_BOOL, "({$chunk.expr} && {$chunk.expr} !== nqp.null_s)", $chunk);
}
}

Expand Down Expand Up @@ -805,12 +805,15 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
self.chunk_sequence($want, @chunks, :$result_child, :$node);
}

proto method cpsify_chunk($chunk) { * }
multi method cpsify_chunk(ChunkCPS $chunk) { $chunk }
multi method cpsify_chunk(Chunk $chunk) {
my $ret := self.chunk_sequence($chunk.type, $chunk.setup, :expr($chunk.expr), :node($chunk.node));
$ret;
}
# proto method cpsify_chunk($chunk) { * }
# multi method cpsify_chunk(ChunkCPS $chunk) { $chunk }
# multi method cpsify_chunk(Chunk $chunk) {
# my $ret := self.chunk_sequence($chunk.type, $chunk.setup, :expr($chunk.expr), :node($chunk.node));
# $ret;
# }

method cpsify_chunk($chunk) { $chunk }
# TODO restore CPS

multi method as_js(QAST::Block $node, :$want, :$cps) {
my $outer := try $*BLOCK;
Expand Down Expand Up @@ -1710,15 +1713,15 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
if $*BINDVAL {
my $bindval := self.as_js_clear_bindval($*BINDVAL, :want($type), :$cps);
if $var.decl eq 'var' {
self.stored_result(Chunk.new($type, "({$*CTX}[{quote_string($var.name)}] = {$bindval.expr})", [$bindval]), :$want);
self.stored_result(Chunk.new($type, "({$*CTX}[{quote_string($var.name)}] = {$bindval.expr})", $bindval), :$want);
}
else {
if $*BLOCK.ctx_for_var($var) -> $ctx {
self.stored_result(Chunk.new($type, "({$ctx}[{quote_string($var.name)}] = {$bindval.expr})", [$bindval]), :$want);
self.stored_result(Chunk.new($type, "({$ctx}[{quote_string($var.name)}] = {$bindval.expr})", $bindval), :$want);
}
else {
# nqp::die("we can't find ctx for {$var.name}");
self.stored_result(Chunk.new($type, "{$*CTX}.bind({quote_string($var.name)}, {$bindval.expr})", [$bindval]), :$want);
self.stored_result(Chunk.new($type, "{$*CTX}.bind({quote_string($var.name)}, {$bindval.expr})", $bindval), :$want);
}
}
}
Expand Down Expand Up @@ -1925,7 +1928,7 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
Chunk.new($T_OBJ, $bindval.expr, [$self, $bindval, "{$self.expr}.\$\$bindattr\${$hint}({$bindval.expr});\n"]);
}
else {
Chunk.new($T_OBJ, "{$self.expr}.\$\$getattr\${$hint}()", [$self]);
Chunk.new($T_OBJ, "{$self.expr}.\$\$getattr\${$hint}()", $self);
}
}
else {
Expand All @@ -1935,15 +1938,15 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
Chunk.new($type, $bindval.expr, [$self, $bindval, "$attr = {$bindval.expr};\n"]);
}
else {
Chunk.new($type, $attr, [$self]);
Chunk.new($type, $attr, $self);
}
}
}
}
elsif $var.scope eq 'contextual' {
if $*BINDVAL {
my $bindval := self.as_js_clear_bindval($*BINDVAL, :want($T_OBJ), :$cps);
self.stored_result(Chunk.new($T_OBJ, "{$*CTX}.bindDynamic({quote_string($var.name)},{$bindval.expr})", [$bindval]), :$want);
self.stored_result(Chunk.new($T_OBJ, "{$*CTX}.bindDynamic({quote_string($var.name)},{$bindval.expr})", $bindval), :$want);
}
else {
Chunk.new($T_OBJ, "{$*CTX}.lookupDynamic({quote_string($var.name)})");
Expand Down
7 changes: 4 additions & 3 deletions src/vm/js/Operations.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,10 @@ class QAST::OperationsJS {
my $obj := $comp.as_js(:want($T_OBJ), $node[0]);
if static_hint($node) -> $hint {
if $type == $T_OBJ {
Chunk.new($T_OBJ, "{$obj.expr}\.\$\$getattr\${$hint}()", [$obj]);
Chunk.new($T_OBJ, "{$obj.expr}\.\$\$getattr\${$hint}()", $obj);
}
else {
Chunk.new($type, "{$obj.expr}\.attr\${$hint}", [$obj]);
Chunk.new($type, "{$obj.expr}\.attr\${$hint}", $obj);
}
}
else {
Expand Down Expand Up @@ -632,7 +632,8 @@ class QAST::OperationsJS {

my $compiled_args := $comp.args($args, :$cont);

my @setup := nqp::clone($compiled_args.setup);
### setup_as_array NYI
my @setup := nqp::clone($compiled_args.setup_as_array);
@setup.unshift($callee);

my $call := $compiled_args.is_args_array ?? '.$$applyCPS(' !! '.$$callCPS(';
Expand Down
4 changes: 2 additions & 2 deletions src/vm/js/RegexCompiler.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -335,12 +335,12 @@ class RegexCompiler {

$call := Chunk.new($T_OBJ,
$!cursor ~ '[' ~ quote_string($method) ~ "]" ~ $invocation ~ $compiled_args.expr ~ ')',
[$compiled_args]);
$compiled_args);
}
else {
#TODO think if arguments are possible, etc.
my $block := $!compiler.as_js($node[0][0], :want($T_OBJ));
$call := Chunk.new($T_OBJ, $block.expr ~ ".\$\$call({$*CTX}, null, $!cursor)", [$block]);
$call := Chunk.new($T_OBJ, $block.expr ~ ".\$\$call({$*CTX}, null, $!cursor)", $block);
}

my $testop := $node.negate ?? '>=' !! '<';
Expand Down

0 comments on commit 3126d69

Please sign in to comment.