Skip to content

Commit

Permalink
[js] Pass native arguments specially
Browse files Browse the repository at this point in the history
  • Loading branch information
pmurias committed Sep 4, 2017
1 parent febba4e commit c9ac792
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 55 deletions.
2 changes: 2 additions & 0 deletions src/vm/js/Chunk.nqp
Expand Up @@ -4,6 +4,8 @@ my $T_INT := 1; # We use a javascript number but always treat it as a 32bit int
my $T_NUM := 2; # We use a javascript number for that
my $T_STR := 3; # We use a javascript str for that
my $T_BOOL := 4; # Something that can be used in boolean context in javascript. To the user it should be presented as a 0 or 1
my $T_CALL_ARG := 5; # Something that will be passed to a sub/method call

my $T_VOID := -1; # Value of this type shouldn't exist, we use a "" as the expr
my $T_NONVAL := -2; # something that is not a nqp value

Expand Down
28 changes: 23 additions & 5 deletions src/vm/js/Compiler.nqp
Expand Up @@ -333,13 +333,13 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
}
}
elsif $arg.named {
my $compiled_arg := self.as_js($arg, :want($T_OBJ));
my $compiled_arg := self.as_js($arg, :want($T_CALL_ARG));
@setup.push($compiled_arg);
@named_exprs.push(quote_string($arg.named) ~ ":" ~ $compiled_arg.expr);

}
else {
my $compiled_arg := self.as_js($arg, :want($T_OBJ));
my $compiled_arg := self.as_js($arg, :want($T_CALL_ARG));
@setup.push($compiled_arg);
@groups[@groups-1].push($compiled_arg.expr);
}
Expand Down Expand Up @@ -408,17 +408,17 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
for @params -> $param {
if $param.slurpy {
if $param.named {
set_variable($param, "nqp.slurpyNamed(_NAMED, {known_named(@*KNOWN_NAMED)})");
set_variable($param, "nqp.slurpyNamed(HLL, _NAMED, {known_named(@*KNOWN_NAMED)})");
}
else {
$pos_slurpy := 1;
set_variable($param, "nqp.slurpyArray(HLL, Array.prototype.slice.call(arguments,{+@sig}))");
set_variable($param, "nqp.slurpyPos(HLL, arguments, {+@sig})");
}
} else {
my int $type := self.type_from_typeobj($param.returns);
my $suffix := self.suffix_from_type($type);
my sub unpack($value) {
"nqp.arg$suffix({$type == $T_OBJ ?? $*CTX !! 'HLL'}, $value)";
"nqp.arg$suffix({$type == $T_OBJ ?? 'HLL' !! $*CTX}, $value)";
}
if $param.named {

Expand Down Expand Up @@ -504,6 +504,24 @@ class QAST::CompilerJS does DWIMYNameMangling does SerializeOnce {
return Chunk.new($T_VOID, "", $chunk.setup);
}

if $desired == $T_CALL_ARG {
if $got == $T_OBJ {
return Chunk.new($T_CALL_ARG, $chunk.expr, $chunk);
}
if $got == $T_BOOL {
return Chunk.new($T_CALL_ARG, "new nqp.NativeIntArg({$chunk.expr} ? 1 : 0)", $chunk);
}
if $got == $T_INT {
return Chunk.new($T_CALL_ARG, "new nqp.NativeIntArg({$chunk.expr})", $chunk);
}
if $got == $T_NUM {
return Chunk.new($T_CALL_ARG, "new nqp.NativeNumArg({$chunk.expr})", $chunk);
}
if $got == $T_STR {
return Chunk.new($T_CALL_ARG, "new nqp.NativeStrArg({$chunk.expr})", $chunk);
}
}

if $desired == $T_NUM {
if $got == $T_INT {
# we store both as a javascript number, and 32bit integers fit into doubles
Expand Down
2 changes: 2 additions & 0 deletions src/vm/js/Operations.nqp
Expand Up @@ -1053,6 +1053,8 @@ class QAST::OperationsJS {
?? $T_OBJ
!! (($operands == 3 || $want == $T_VOID) ?? $T_BOOL !! $want);

$cond_type := $T_OBJ if $cond_type == $T_CALL_ARG;

# The 2 operand form of if in a non-void context also uses the cond as the return value
my $cond := $comp.as_js($node[0], :want($cond_type));
my $then;
Expand Down
12 changes: 5 additions & 7 deletions src/vm/js/nqp-runtime/bootstrap.js
Expand Up @@ -38,11 +38,9 @@ function createKnowHOWAttribute() {
};
methods['new'] = function(ctx, _NAMED, self) {
var attr = r.allocate(self._STable);
// TODO convert to string
attr.__name = _NAMED.name;
attr.__name = _NAMED.name.$$getStr();
attr.__type = _NAMED.type;
// TODO convert to int
attr.__boxTarget = _NAMED.box_target ? _NAMED.box_target : 0;
attr.__boxTarget = _NAMED.box_target ? _NAMED.box_target.$$getInt() : 0;
return attr;
};

Expand Down Expand Up @@ -110,7 +108,7 @@ addKnowhowHowMethod('new_type', function(ctx, _NAMED, self) {
var HOW = self._STable.REPR.allocate(self._STable);

/* See if we have a representation name; if not default to P6opaque. */
var reprName = (_NAMED && _NAMED.repr) ? _NAMED.repr : 'P6opaque';
var reprName = (_NAMED && _NAMED.repr) ? _NAMED.repr.$$getStr() : 'P6opaque';

/* Create a new type object of the desired REPR. (Note that we can't
* default to KnowHOWREPR here, since it doesn't know how to actually
Expand All @@ -119,7 +117,7 @@ addKnowhowHowMethod('new_type', function(ctx, _NAMED, self) {

/* See if we were given a name; put it into the meta-object if so. */
if (_NAMED && _NAMED.name) {
HOW.__name = _NAMED.name;
HOW.__name = typeof _NAMED.name === 'string' ? _NAMED.name : _NAMED.name.$$getStr();
} else {
HOW.__name = null;
}
Expand All @@ -135,7 +133,7 @@ addKnowhowHowMethod('add_attribute', function(ctx, _NAMED, self, type, attr) {
});

addKnowhowHowMethod('add_method', function(ctx, _NAMED, self, type, name, code) {
self.__methods.content.set(name, code);
self.__methods.content.set(name === 'string' ? name : name.$$getStr(), code);
});

addKnowhowHowMethod('compose', function(ctx, _NAMED, self, typeObject) {
Expand Down
85 changes: 80 additions & 5 deletions src/vm/js/nqp-runtime/core.js
Expand Up @@ -97,11 +97,74 @@ exports.hash = function() {
return new Hash();
};

exports.slurpyNamed = function(named, skip) {
var hash = new Hash();
const nativeArgs = require('./native-args.js');
const NativeIntArg = nativeArgs.NativeIntArg;
const NativeNumArg = nativeArgs.NativeNumArg;
const NativeStrArg = nativeArgs.NativeStrArg;

const intToObj = exports.intToObj = function(currentHLL, i) {
const type = currentHLL.get('int_box');
if (!type) {
return new NQPInt(i);
} else {
var repr = type._STable.REPR;
var obj = repr.allocate(type._STable);
obj.$$setInt(i);
return obj;
}
};

const numToObj = exports.numToObj = function(currentHLL, n) {
const type = currentHLL.get('num_box');
if (!type) {
return n;
} else {
var repr = type._STable.REPR;
var obj = repr.allocate(type._STable);
obj.$$setNum(n);
return obj;
}
};

const strToObj = exports.strToObj = function(currentHLL, s) {
const type = currentHLL.get('str_box');
if (!type) {
return s;
} else {
var repr = type._STable.REPR;
var obj = repr.allocate(type._STable);
obj.$$setStr(s);
return obj;
}
};

const arg = exports.arg = function(currentHLL, arg) {
if (arg instanceof NativeIntArg) {
return intToObj(currentHLL, arg.value);
}
else if (arg instanceof NativeNumArg) {
return numToObj(currentHLL, arg.value);
}
else if (arg instanceof NativeStrArg) {
return strToObj(currentHLL, arg.value);
} else {
return arg;
}
};

exports.slurpyPos = function(currentHLL, args, from) {
const unpacked = new Array(args.length - from);
for (let i=from; i < args.length; i++) {
unpacked[i-from] = arg(currentHLL, args[i]);
}
return hll.slurpyArray(currentHLL, unpacked);
};

exports.slurpyNamed = function(currentHLL, named, skip) {
const hash = new Hash();
for (key in named) {
if (!skip[key]) {
hash.content.set(key, named[key]);
hash.content.set(key, arg(currentHLL, named[key]));
}
}
return hash;
Expand Down Expand Up @@ -468,7 +531,13 @@ function fromJS(obj) {
}

function toJS(obj) {
if (obj instanceof NQPInt) {
if (obj instanceof NativeIntArg) {
return obj.value;
} else if (obj instanceof NativeNumArg) {
return obj.value;
} else if (obj instanceof NativeStrArg) {
return obj.value;
} else if (obj instanceof NQPInt) {
return obj.value;
} else if (obj instanceof CodeRef) {
return function() {
Expand Down Expand Up @@ -1153,7 +1222,13 @@ op.ctxouterskipthunks = function(ctx) {
};

op.captureposprimspec = function(capture, idx) {
if (capture.pos[idx].typeObject_) {
if (capture.pos[idx] instanceof NativeIntArg) {
return 1;
} else if (capture.pos[idx] instanceof NativeNumArg) {
return 2;
} else if (capture.pos[idx] instanceof NativeStrArg) {
return 3;
} else if (capture.pos[idx].typeObject_) {
return 0;
} else {
return op.objprimspec(capture.pos[idx]);
Expand Down
47 changes: 47 additions & 0 deletions src/vm/js/nqp-runtime/native-args.js
@@ -0,0 +1,47 @@
class NativeIntArg {
constructor(value) {
this.value = value;
}

$$getInt() {
return this.value;
}

$$decont() {
return this;
}
};

exports.NativeIntArg = NativeIntArg;

class NativeNumArg {
constructor(value) {
this.value = value;
}

$$getNum() {
return this.value;
}

$$decont() {
return this;
}
};

exports.NativeNumArg = NativeNumArg;

class NativeStrArg {
constructor(value) {
this.value = value;
}

$$getStr() {
return this.value;
}

$$decont() {
return this;
}
};

exports.NativeStrArg = NativeStrArg;
74 changes: 36 additions & 38 deletions src/vm/js/nqp-runtime/runtime.js
Expand Up @@ -16,6 +16,12 @@ var StaticCtx = require('./static-ctx.js');

const BOOT = require('./BOOT.js');

const nativeArgs = require('./native-args.js');

exports.NativeIntArg = nativeArgs.NativeIntArg;
exports.NativeNumArg = nativeArgs.NativeNumArg;
exports.NativeStrArg = nativeArgs.NativeStrArg;

const fs = require('fs');

exports.NQPInt = NQPInt;
Expand All @@ -32,8 +38,14 @@ var core = require('./core');
loadOps(core);
exports.hash = core.hash;
exports.slurpyNamed = core.slurpyNamed;
exports.slurpyPos = core.slurpyPos;
exports.named = core.named;
exports.unwrapNamed = core.unwrapNamed;
exports.arg = core.arg;

exports.intToObj = core.intToObj;
exports.numToObj = core.numToObj;
exports.strToObj = core.strToObj;

exports.EvalResult = core.EvalResult;

Expand Down Expand Up @@ -262,41 +274,6 @@ exports.toInt = function(arg, ctx) {
return (exports.toNum(arg, ctx) | 0);
};

exports.intToObj = function(currentHLL, i) {
const type = currentHLL.get('int_box');
if (!type) {
return new NQPInt(i);
} else {
var repr = type._STable.REPR;
var obj = repr.allocate(type._STable);
obj.$$setInt(i);
return obj;
}
};

exports.numToObj = function(currentHLL, n) {
const type = currentHLL.get('num_box');
if (!type) {
return n;
} else {
var repr = type._STable.REPR;
var obj = repr.allocate(type._STable);
obj.$$setNum(n);
return obj;
}
};

exports.strToObj = function(currentHLL, s) {
const type = currentHLL.get('str_box');
if (!type) {
return s;
} else {
var repr = type._STable.REPR;
var obj = repr.allocate(type._STable);
obj.$$setStr(s);
return obj;
}
};

if (!Math.imul) {
/* Polyfill from:
Expand Down Expand Up @@ -507,9 +484,6 @@ exports.tooManyPos = function(got, expected) {
throw new NQPException(`Too many positionals passed; expected ${expected} arguments but got ${got-2}`);
};

exports.arg = function(HLL, arg) {
return arg;
};

exports.arg_i = function(ctx, contedArg) {
const arg = contedArg.$$decont(ctx);
Expand Down Expand Up @@ -548,3 +522,27 @@ exports.arg_s = function(ctx, contedArg) {
exports.missingNamed = function(name) {
throw new NQPException(`Required named parameter '${name}' not passed`);
};


const chunkNamesToTypes = {
T_OBJ: 0,
T_INT: 1,
T_NUM: 2,
T_STR: 3,
T_BOOL: 4,
T_CALL_ARG: 5,

T_VOID: -1,
T_NONVAL: -2,
T_ARGS: -3,
T_ARGS_ARRAY: -4,
};

const chunkTypesToNames = {};
for (let name of Object.keys(chunkNamesToTypes)) {
chunkTypesToNames[chunkNamesToTypes[name]] = name;
}

exports.coercion = function(got, expected) {
throw new Error("Can't convert, got: " + chunkTypesToNames[got] + ' expected:' + chunkTypesToNames[expected]);
};

0 comments on commit c9ac792

Please sign in to comment.