Skip to content

Commit 15805af

Browse files
committed
[js] Adapt things so that more lexicals can be compiled as dynamic variables.
1 parent 4d61b1f commit 15805af

File tree

1 file changed

+66
-43
lines changed

1 file changed

+66
-43
lines changed

src/vm/js/Compiler.nqp

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,15 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
341341
@sig.push($cps);
342342
}
343343

344+
my sub set_variable($var, $value) {
345+
if self.is_dynamic_var($var) {
346+
@setup.push("{$*CTX}[{quote_string($var.name)}] = $value;\n");
347+
}
348+
else {
349+
$*BLOCK.add_js_lexical(self.mangle_name($var.name));
350+
@setup.push("{self.mangle_name($var.name)} = $value;\n");
351+
}
352+
}
344353

345354
my $handled_this := 0;
346355
my $bind_named := '';
@@ -353,7 +362,6 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
353362
else {
354363
$slurpy := $_;
355364
}
356-
$*BLOCK.add_js_lexical(self.mangle_name($_.name));
357365
}
358366
elsif $_.named {
359367
my $quoted := quote_string($_.named);
@@ -372,14 +380,7 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
372380

373381
# TODO required named arguments and defaultless optional ones
374382

375-
if self.is_dynamic_var($_) {
376-
@setup.push("{$*CTX}[{quote_string($_.name)}] = $value;\n");
377-
}
378-
else {
379-
$*BLOCK.add_js_lexical(self.mangle_name($_.name));
380-
@setup.push("{self.mangle_name($_.name)} = $value;\n");
381-
}
382-
383+
set_variable($_, $value);
383384
}
384385
elsif self.is_dynamic_var($_) {
385386
my $tmp := self.unique_var('param');
@@ -430,10 +431,10 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
430431
}
431432

432433
if $slurpy {
433-
@setup.push("{self.mangle_name($slurpy.name)} = new nqp.NQPArray(Array.prototype.slice.call(arguments,{+@sig}));\n");
434+
set_variable($slurpy, "new nqp.NQPArray(Array.prototype.slice.call(arguments,{+@sig}))");
434435
}
435436
if $slurpy_named {
436-
@setup.push("{self.mangle_name($slurpy_named.name)} = nqp.slurpy_named(_NAMED, {known_named(@*KNOWN_NAMED)});\n");
437+
set_variable($slurpy_named, "nqp.slurpy_named(_NAMED, {known_named(@*KNOWN_NAMED)})");
437438
}
438439

439440
Chunk.new($T_NONVAL, nqp::join(',', @sig), @setup);
@@ -868,8 +869,8 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
868869

869870
if $expected_outer.cuid ne $*BLOCK.cuid {
870871
@capture_inners.push("(function() \{\n");
871-
@capture_inners.push(self.import_stuff_from_setting($*SETTING_TARGET));
872872
@capture_inners.push("var {$expected_outer.ctx} = null;\n");
873+
@capture_inners.push(self.import_stuff_from_setting($*SETTING_TARGET));
873874
}
874875

875876
if %*BLOCKS_AS_METHOD{$_.key} {
@@ -892,6 +893,9 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
892893

893894
# Should we compile it to a form that's more efficent when used as a method
894895
method looks_like_a_method(QAST::Block $block) {
896+
# Disable it as we currently don't make use of it at runtime
897+
return 0;
898+
895899
if $block.blocktype eq 'declaration_static'
896900
&& nqp::istype($block[0], QAST::Stmts)
897901
&& nqp::istype($block[0][0], QAST::Var)
@@ -948,10 +952,10 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
948952

949953
my @function := [
950954
"function({$sig.expr}) \{\n",
951-
self.setup_setting($node),
952955
self.declare_js_vars($*BLOCK.tmps),
953956
self.declare_js_vars($*BLOCK.js_lexicals),
954957
$create_ctx,
958+
self.setup_setting($node),
955959
$sig,
956960
self.clone_inners($*BLOCK),
957961
self.capture_inners($*BLOCK),
@@ -997,10 +1001,10 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
9971001

9981002
my @function_cps := [
9991003
"function({$sig_cps.expr}) \{\n",
1000-
self.setup_setting($node),
10011004
self.declare_js_vars($*BLOCK.tmps),
10021005
self.declare_js_vars($*BLOCK.js_lexicals),
10031006
$create_ctx,
1007+
self.setup_setting($node),
10041008
$sig_cps,
10051009
self.clone_inners($*BLOCK),
10061010
self.capture_inners($*BLOCK),
@@ -1114,12 +1118,18 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
11141118
if self.is_ctxsave($node) {
11151119
my @lexicals;
11161120
for $*BLOCK.variables -> $var {
1121+
my $value;
11171122
if $*BLOCK.lookup_static_variable($var) -> $static {
1118-
@lexicals.push(quote_string($var.name) ~ ': ' ~ self.value_as_js($static.value));
1123+
$value := self.value_as_js($static.value);
1124+
}
1125+
elsif self.is_dynamic_var($var) {
1126+
$value := "{$*CTX}.lookup({quote_string($var.name)})";
11191127
}
11201128
else {
1121-
@lexicals.push(quote_string($var.name) ~ ': ' ~ self.mangle_name($var.name));
1129+
$value := self.mangle_name($var.name);
11221130
}
1131+
@lexicals.push(quote_string($var.name) ~ ': ' ~ $value);
1132+
11231133
}
11241134
Chunk.void("nqp.ctxsave(\{{nqp::join(',', @lexicals)}\});\n");
11251135
}
@@ -1477,41 +1487,54 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
14771487
$T_OBJ;
14781488
}
14791489

1480-
method compile_var(QAST::Var $var, :$cps) {
1481-
if self.var_is_lexicalish($var) && self.is_dynamic_var($var) {
1482-
if $*BINDVAL {
1483-
my $bindval := self.as_js_clear_bindval($*BINDVAL, :want($T_OBJ), :$cps);
1484-
if $var.decl eq 'var' {
1485-
self.stored_result(Chunk.new($T_OBJ, "({$*CTX}[{quote_string($var.name)}] = {$bindval.expr})", [$bindval]));
1486-
}
1487-
else {
1488-
self.stored_result(Chunk.new($T_OBJ, "{$*CTX}.bind({quote_string($var.name)}, {$bindval.expr})", [$bindval]));
1489-
}
1490+
method compile_var_as_js_var(QAST::Var $var, :$cps) {
1491+
my $type := self.figure_out_type($var);
1492+
my $mangled := self.mangle_name($var.name);
1493+
if $*BINDVAL {
1494+
# TODO better source mapping
1495+
# TODO use the proper type
1496+
my $bindval := self.as_js_clear_bindval($*BINDVAL, :want($type), :$cps);
1497+
self.cpsify_chunk(Chunk.new($type,$mangled, [$bindval,'('~$mangled~' = ('~ $bindval.expr ~ "));\n"]));
1498+
}
1499+
else {
1500+
# TODO get the proper type
1501+
self.cpsify_chunk(Chunk.new($type, $mangled, [], :node($var)));
1502+
}
1503+
}
1504+
1505+
method compile_var_as_part_of_ctx(QAST::Var $var, :$cps) {
1506+
if $*BINDVAL {
1507+
my $bindval := self.as_js_clear_bindval($*BINDVAL, :want($T_OBJ), :$cps);
1508+
if $var.decl eq 'var' {
1509+
self.stored_result(Chunk.new($T_OBJ, "({$*CTX}[{quote_string($var.name)}] = {$bindval.expr})", [$bindval]));
14901510
}
14911511
else {
1492-
if $var.decl eq 'var' {
1493-
self.stored_result(Chunk.new($T_OBJ, "({$*CTX}[{quote_string($var.name)}] = null)", []));
1494-
}
1495-
else {
1496-
Chunk.new($T_OBJ, "{$*CTX}.lookup({quote_string($var.name)})", [], :node($var));
1497-
}
1512+
self.stored_result(Chunk.new($T_OBJ, "{$*CTX}.bind({quote_string($var.name)}, {$bindval.expr})", [$bindval]));
14981513
}
14991514
}
1500-
elsif $*BLOCK.lookup_static_variable($var) -> $static {
1515+
else {
1516+
if $var.decl eq 'var' {
1517+
self.stored_result(Chunk.new($T_OBJ, "({$*CTX}[{quote_string($var.name)}] = null)", []));
1518+
}
1519+
else {
1520+
Chunk.new($T_OBJ, "{$*CTX}.lookup({quote_string($var.name)})", [], :node($var));
1521+
}
1522+
}
1523+
}
1524+
1525+
method compile_var(QAST::Var $var, :$cps) {
1526+
if $*BLOCK.lookup_static_variable($var) -> $static {
15011527
Chunk.new($T_OBJ, self.value_as_js($static.value), []);
15021528
}
1503-
elsif self.var_is_lexicalish($var) || $var.scope eq 'local' {
1504-
my $type := self.figure_out_type($var);
1505-
my $mangled := self.mangle_name($var.name);
1506-
if $*BINDVAL {
1507-
# TODO better source mapping
1508-
# TODO use the proper type
1509-
my $bindval := self.as_js_clear_bindval($*BINDVAL, :want($type), :$cps);
1510-
self.cpsify_chunk(Chunk.new($type,$mangled, [$bindval,'('~$mangled~' = ('~ $bindval.expr ~ "));\n"]));
1529+
elsif $var.scope eq 'local' {
1530+
self.compile_var_as_js_var($var, :$cps);
1531+
}
1532+
elsif self.var_is_lexicalish($var) {
1533+
if self.is_dynamic_var($var) {
1534+
self.compile_var_as_part_of_ctx($var, :$cps);
15111535
}
15121536
else {
1513-
# TODO get the proper type
1514-
self.cpsify_chunk(Chunk.new($type, $mangled, [], :node($var)));
1537+
self.compile_var_as_js_var($var, :$cps);
15151538
}
15161539
}
15171540
elsif ($var.scope eq 'positional') {

0 commit comments

Comments
 (0)