Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Wrap subs in a CodeRef object.
  • Loading branch information
pmurias committed Sep 26, 2014
1 parent 9158711 commit c2f2d39
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 16 deletions.
40 changes: 29 additions & 11 deletions src/vm/js/QAST/Compiler.nqp
Expand Up @@ -398,9 +398,11 @@ class QAST::OperationsJS {

# TODO - think if it's the correct thing to do
add_op('takeclosure', sub ($comp, $node, :$want) {
$comp.as_js($node[0], :want($T_OBJ));
$comp.as_js($node[0], :want($T_OBJ))~'.takeclosure()';
});

add_simple_op('takeclosure', $T_OBJ, [$T_OBJ], sub ($closure) {"$closure.takeclosure()"});

add_op('istrue', sub ($comp, $node, :$want) {
$comp.as_js($node[0], :want($T_BOOL));
});
Expand Down Expand Up @@ -482,7 +484,7 @@ class QAST::OperationsJS {
$compiled_args := merge_arg_groups($compiled_args);
$call := '.apply(undefined,';
} else {
$call := '(';
$call := '.$call(';
}

$comp.stored_result(
Expand Down Expand Up @@ -1158,14 +1160,15 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
self.compile_block($node, $outer, :$want);
}

method mangled_cuid($node) {
method mangled_cuid($cuid) {
my $ret := '';
for nqp::split('',$node.cuid) -> $c {
for nqp::split('',$cuid) -> $c {
$ret := $ret ~ ($c eq '.' ?? '_' !! $c);
}
$ret;
}


has %!cuids;

method register_cuid($node) {
Expand All @@ -1176,6 +1179,14 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
nqp::existskey(%!cuids, $node.cuid);
}

method setup_cuids() {
my @cuids;
for %!cuids {
@cuids.push("{self.mangled_cuid($_.key)} = new nqp.CodeRef()");
}
self.declare_js_vars(@cuids);
}

method stored_result($chunk, :$want) {
if $chunk.type == $T_VOID || $want == $T_VOID {
Chunk.new($T_VOID, '', [$chunk, $chunk.expr~";\n"]);
Expand All @@ -1186,7 +1197,7 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
}

method compile_block(QAST::Block $node, $outer, :$want, :$arg='') {
my $cuid := self.mangled_cuid($node);
my $cuid := self.mangled_cuid($node.cuid);

my $setup;

Expand All @@ -1206,19 +1217,19 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
my $sig := self.compile_sig($*BLOCK.params);

$setup := [
"$cuid = function({$sig.expr}) \{",
"$cuid.block(function({$sig.expr}) \{",
self.declare_js_vars($*BLOCK.tmps),
self.declare_js_vars($*BLOCK.js_lexicals),
$sig,
$create_ctx,
$stmts,
"return {$stmts.expr};\n",
"\};\n"];
"\});\n"];
}

if $node.blocktype eq 'immediate' {
my $extra_args := $arg ?? ",$arg" !! '';
self.stored_result(Chunk.new($want, $cuid~"({$outer.ctx},\{\}$extra_args)", $setup, :$node), :$want);
self.stored_result(Chunk.new($want, $cuid~".\$call({$outer.ctx},\{\}$extra_args)", $setup, :$node), :$want);
} else {
Chunk.new($T_OBJ, $cuid, $setup);
}
Expand Down Expand Up @@ -1294,9 +1305,16 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {

my $quoted_data := nqp::isnull_s($sc_data) ?? 'null' !! quote_string($sc_data);

my $code_ref_blocks := $ast.code_ref_blocks();

my @blocks;
for $code_ref_blocks -> $block {
@blocks.push(self.mangled_cuid($block.cuid));
}

"var sh=[{nqp::join(',',@sh)}];\n"
~ "var sc = nqp.op.createsc({quote_string(nqp::scgethandle($sc))});\n"
~ "var code_refs = [];\n" # TODO
~ "var code_refs = [{nqp::join(',',@blocks)}];\n" # TODO
~ "nqp.op.deserialize($quoted_data,sc,sh,code_refs,null);\n"
~ "nqp.op.scsetdesc(sc,{quote_string(nqp::scgetdesc($sc))});\n"
}
Expand All @@ -1317,13 +1335,13 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {

my $main := self.as_js($main_block, :want($T_VOID));

$body := Chunk.new($T_VOID, "", [$block_js, $main, self.mangled_cuid($main_block) ~ "();\n"]);
$body := Chunk.new($T_VOID, "", [$block_js, $main, self.mangled_cuid($main_block.cuid) ~ ".\$call();\n"]);

} else {
$body := $block_js;
}

Chunk.new($T_VOID, "", [self.create_sc($node), $body]);
Chunk.new($T_VOID, "", [self.setup_cuids(), self.create_sc($node), $body]);

}

Expand Down
18 changes: 18 additions & 0 deletions src/vm/js/nqp-runtime/code-ref.js
@@ -0,0 +1,18 @@
function CodeRef() {
}

CodeRef.prototype.block = function(func) {
this.$call = func;
};

CodeRef.prototype.apply = function(thisArg, argsArray) {
return this.$call.apply(thisArg, argsArray);
};

CodeRef.prototype.takeclosure = function() {
var closure = new CodeRef;
closure.$call = this.$call;
return closure;
};

module.exports = CodeRef;
11 changes: 8 additions & 3 deletions src/vm/js/nqp-runtime/core.js
Expand Up @@ -2,11 +2,16 @@ var op = {};
exports.op = op;

var Hash = require('./hash.js');
var CodeRef = require('./code-ref.js');

exports.CodeRef = CodeRef;

op.getcomp = function(lang) {
if (lang == 'JavaScript') {
return function(ctx, named, code) {
return eval(code);
return {
eval: function(ctx, named, code) {
return eval(code);
}
};
} else if (lang == 'nqp') {
return {
Expand All @@ -22,7 +27,7 @@ op.getcomp = function(lang) {
};

op.isinvokable = function(obj) {
return (typeof obj == 'function' ? 1 : 0);
return (obj instanceof CodeRef ? 1 : 0);
};

op.escape = function(str) {
Expand Down
2 changes: 1 addition & 1 deletion src/vm/js/nqp-runtime/deserialization.js
Expand Up @@ -166,7 +166,7 @@ BinaryCursor.prototype.STable = function(STable) {

var method_cache = this.variant();

// console.log("method_cache", method_cache);
//console.log("method_cache", method_cache);

//TODO: maybe we should just get rid of the vtable
var vtable = [];
Expand Down
2 changes: 2 additions & 0 deletions src/vm/js/nqp-runtime/runtime.js
Expand Up @@ -19,6 +19,7 @@ var deserialization = require('./deserialization.js');
exports.wval = deserialization.wval;
load_ops(deserialization);

exports.CodeRef = require('./code-ref.js');

exports.to_str = function(arg) {
if (typeof arg == 'number') {
Expand Down Expand Up @@ -88,3 +89,4 @@ if (!Math.imul) {
exports.top_context = function() {
return null;
};

2 changes: 1 addition & 1 deletion t/js/getcomp-js.t
@@ -1,4 +1,4 @@
plan(1);
my $comp := nqp::getcomp('JavaScript');
my $helloworld := $comp('"Hello " + "World"');
my $helloworld := $comp.eval('"Hello " + "World"');
ok($helloworld eq 'Hello World',"getting a simple string from JavaScript");

0 comments on commit c2f2d39

Please sign in to comment.