// This is the part of the Prelude for JavaScript which is written in
// JavaScript. See lib6/Prelude/JS.pm for the part written in Perl 6.
// Ensure the MetaModel is loaded.
try { Perl6.Object } catch(err) {
var error = new Error("Perl6.MetaModel not loaded; aborting.");
alert(error);
throw(error);
}
// Test Perl5 support
if(typeof(Perl5) == 'undefined') Perl5 = undefined;
// Create our namespace.
if(PIL2JS == undefined) var PIL2JS = {};
// Trick to speed up PIL2JS, by putter:
// We'll lexicalize PIL2JS in all functions by "var PIL2JS = AlsoPIL2JS".
// This gives a ~~10% speedup, as PIL2JS is then a nice local variable instead
// of a global one.
var AlsoPIL2JS_SpeedupHack = PIL2JS;
// Optimization, needed by P5 Prelude::JS
PIL2JS.if_undefined = function (thing, otherwise) {
return thing == undefined ? otherwise : thing;
}
// IE doesn't care about standards and only interprets "\r" as linefeed.
PIL2JS.LF =
typeof document != "undefined" &&
typeof document.all != "undefined" &&
navigator.userAgent.indexOf("Konqueror") == -1
? "\r"
: "\n";
PIL2JS.cur_uid = 1;
PIL2JS.new_uid = function () {
return PIL2JS.cur_uid++;
};
// Hash class. As with the various exception classes above, we don't need to
// declare any methods. This class only exists so code can do if(foo instanceof
// PIL2JS.Hash) {...}.
PIL2JS.Hash = function () { this.entries = {}; this.num_of_entries = 0 };
PIL2JS.Hash.prototype.add_pair = function (pair) {
var key = pair.key.toNative();
if(!this.entries[key]) this.num_of_entries++;
this.entries[key] = pair;
};
PIL2JS.Hash.prototype.exists = function (key) {
var ikey = key.toNative();
return this.entries[ikey] != undefined;
};
PIL2JS.Hash.prototype.delete_key = function (key) {
var old = this.get_value(key),
key = key.toNative();
if(this.entries[key]) this.num_of_entries--;
delete this.entries[key];
return old;
};
PIL2JS.Hash.prototype.pairs = function () {
var pairs = [];
for(var internal_key in this.entries) {
pairs.push(this.entries[internal_key]);
}
return pairs;
};
PIL2JS.Hash.prototype.keys = function () {
var keys = [];
var pairs = this.pairs();
for(var i = 0; i < pairs.length; i++) {
keys.push(pairs[i].key);
}
return keys;
};
PIL2JS.Hash.prototype.get_value = function (key) {
return this.exists(key) ? this.entries[key.toNative()].value : undefined;
};
PIL2JS.Hash.prototype.toString = function () { return "<PIL2JS.Hash>" };
// class Pair { has $.key; has $.value }
PIL2JS.Pair = function (key, value) {
this.key = key;
this.value = value;
};
PIL2JS.Pair.prototype.toString = function () { return "<PIL2JS.Pair>" };
// class PIL2JS::Internals::NamedPair { has "native_js_str" $.key; has $.value }
PIL2JS.NamedPair = function (key, value) {
this.key = key;
this.value = value;
};
PIL2JS.NamedPair.prototype.toString = function () { return "<PIL2JS.NamedPair>" };
// class Ref { has $.referencee }
PIL2JS.Ref = function (referencee) {
this.referencee = referencee;
this.autoderef = referencee.FETCH() instanceof Array
|| referencee.FETCH() instanceof PIL2JS.Hash;
// || referencee instanceof PIL2JS.OwnObject will be needed later, see
// http://www.nntp.perl.org/group/perl.perl6.language/22532.
return this;
};
PIL2JS.Ref.prototype.toString = function () { return "<PIL2JS.Ref>" };
// class Multi { has @.variants; method add_variant (Code &f) {...} }
PIL2JS.Multi = function () { this.variants = [] };
PIL2JS.Multi.prototype.add_variant = function (code, arity) {
this.variants.push({ code: code, arity: arity });
};
PIL2JS.Multi.prototype.run = function (args) {
var orig_args = [].concat(args);
var cxt = args.shift(), cc = args.pop();
args = PIL2JS.possibly_flatten(args);
var argc = args.length;
var candidates = [];
for(var i = 0; i < this.variants.length; i++) {
if(this.variants[i].arity == argc) {
candidates.push(this.variants[i]);
}
}
if(candidates.length == 0) {
// Hack?
for(var i = 0; i < this.variants.length; i++) {
var pargs = [].concat(orig_args);
pargs.only_check_for_params = true;
var ok = true;
try { this.variants[i].code.FETCH()(pargs) } catch(err) {
// The sub wasn't able to bind pargs to its parameters.
ok = false;
}
// Was the sub able to bind pargs to its parameters?
if(ok) {
// Yes, so add the sub to our candidate list!
candidates.push(this.variants[i]);
}
}
}
if(candidates.length == 0) {
PIL2JS.die("No suitable multi variant found!");
} else if(candidates.length > 1) {
PIL2JS.warn("More than one suitable multi variant found, using first one.");
}
return candidates[0].code.FETCH()(orig_args);
};
PIL2JS.new_multi = function () {
var multi = new PIL2JS.Multi;
var f = function (args) { return multi.run(args) };
f.pil2js_multi = multi;
return f;
};
// This is necessary to emulate pass by ref, needed by is rw and is ref.
// See section "DESIGN" in README.
// FETCH :: SomeNativeType
// STORE :: SomeBox -> TheSameBox
// BINDTO :: SomeBox -> TheSameBox
// PIL2JS.Box is a plain normal variable container, which can be assigned to
// and rebound.
PIL2JS.Box = function (value) {
this.FETCH = function () { return value };
this.STORE = function (n) {
var new_val = n.FETCH();
var my_ctype = this.container_type;
var new_ctype = n.container_type;
var rebox_array_rw = function (iarray) {
var oarray = [];
for(var i = 0; i < iarray.length; i++) {
oarray[i] = new PIL2JS.Box(iarray[i].FETCH());
}
return oarray;
};
// Rewrite rules (kind of context simulation)
// my @a = "hi" --> my @a = ("hi",)
if(
my_ctype == PIL2JS.ContainerType.Array &&
new_ctype == PIL2JS.ContainerType.Scalar
) {
new_val = rebox_array_rw([n]);
// my @a = %h
} else if(
my_ctype == PIL2JS.ContainerType.Array &&
new_ctype == PIL2JS.ContainerType.Hash
) {
var pairs = new_val.pairs();
for(var i = 0; i < pairs.length; i++) {
pairs[i] = new PIL2JS.Box(pairs[i].FETCH());
}
new_val = pairs;
// my @a = @b (copy @b, don't bind)
} else if(
my_ctype == PIL2JS.ContainerType.Array &&
new_ctype == PIL2JS.ContainerType.Array
) {
new_val = rebox_array_rw(new_val);
// my %a = (a => 1, b => 2) (or generally my %a = @a) --> my %a = hash(a => 1, b => 2)
} else if(
my_ctype == PIL2JS.ContainerType.Hash &&
new_ctype == PIL2JS.ContainerType.Array
) {
new_val = PIL2JS.cps2normal(
_26Main_3a_3ahash.FETCH(),
[PIL2JS.Context.SlurpyAny].concat(new_val)
).FETCH();
// my %a = %b (copy %b, don't bind)
} else if(
my_ctype == PIL2JS.ContainerType.Hash &&
new_ctype == PIL2JS.ContainerType.Hash
) {
var pairs = new_val.pairs();
for(var i = 0; i < pairs.length; i++) {
pairs[i] = new PIL2JS.Box.Constant(pairs[i]);
}
// &hash takes care of the copying.
new_val =
PIL2JS.cps2normal(
_26Main_3a_3ahash.FETCH(), [PIL2JS.Context.SlurpyAny].concat(pairs)
).FETCH();
// my %a = (a => 1) or my %a = 10
} else if(
my_ctype == PIL2JS.ContainerType.Hash &&
new_ctype == PIL2JS.ContainerType.Scalar
) {
new_val = PIL2JS.cps2normal(
_26Main_3a_3ahash.FETCH(),
[PIL2JS.Context.SlurpyAny, n]
).FETCH();
// my $scalar = @array or my $scalar = %hash (should auto-ref)
} else if(
my_ctype == PIL2JS.ContainerType.Scalar &&
new_ctype != PIL2JS.ContainerType.Scalar
) {
new_val = PIL2JS.cps2normal(
_26Main_3a_3aprefix_3a_5c.FETCH(), [PIL2JS.Context.ItemAny, n]
).FETCH();
} else if(
my_ctype == PIL2JS.ContainerType.Scalar &&
new_ctype == PIL2JS.ContainerType.Scalar
) {
} else {
PIL2JS.die("XXX should never happen");
}
value = new_val;
return this;
};
this.uid = PIL2JS.new_uid();
this.container_type = PIL2JS.container_type(value);
};
PIL2JS.Box.prototype = {
BINDTO: function (other) {
if(
(this.uid != undefined && other.uid != undefined && this.uid == other.uid) ||
(this.uid == undefined && other.uid == undefined && this.FETCH() == other.FETCH())
) {
// PIL2JS.die("Binding would create a bind cycle!");
// Bind cycles are actually legal.
}
var fetch = other.FETCH, my_ctype = this.container_type,
store = other.STORE, other_ctype = other.container_type;
// No problem: $foo := $bar
if(my_ctype == other_ctype) {
this.FETCH = fetch;
this.STORE = function (n) { store.call(other, n); return this };
this.uid = other.uid;
this.isConstant = other.isConstant;
// Problematic: $foo := @array, $foo := %hash
// See http://www.nntp.perl.org/group/perl.perl6.language/22541:
// Right, so I guess what really happens is ref autogeneration in that
// case, and there's no difference between
//
// $x = [at]array;
// $x := [at]array;
//
// Hey, who said anything about consistency? :-)
} else if(my_ctype == PIL2JS.ContainerType.Scalar) {
var val = fetch();
this.FETCH = function () { return new PIL2JS.Ref(new PIL2JS.Box.Constant(val)) };
this.STORE = function (n) { val = n.FETCH(); return this };
this.uid = other.uid;
this.isConstant = other.isConstant;
} else if(my_ctype == PIL2JS.ContainerType.Array && other_ctype == PIL2JS.ContainerType.Scalar) {
var other_val = fetch();
if(other_val instanceof PIL2JS.Ref && other_val.autoderef && other_val.referencee.FETCH() instanceof Array) {
// Ok.
var other_box = other_val.referencee;
this.FETCH = other_box.FETCH;
this.STORE = other_box.STORE;
this.uid = other.uid;
this.isConstant = other.isConstant;
} else {
PIL2JS.die("Can't use object of type \"" + PIL2JS.cps2normal(_26Main_3a_3aref.FETCH(), [PIL2JS.Context.ItemAny, other]).toNative() + "\" as an array or array reference!");
}
} else if(my_ctype == PIL2JS.ContainerType.Hash && other_ctype == PIL2JS.ContainerType.Scalar) {
var other_val = fetch();
if(other_val instanceof PIL2JS.Ref && other_val.autoderef && other_val.referencee.FETCH() instanceof PIL2JS.Hash) {
// Ok.
var other_box = other_val.referencee;
this.FETCH = other_box.FETCH;
this.STORE = other_box.STORE;
this.uid = other.uid;
this.isConstant = other.isConstant;
} else {
PIL2JS.die("Can't use object of type \"" + PIL2JS.cps2normal(_26Main_3a_3aref.FETCH(), [PIL2JS.Context.ItemAny, other]).toNative() + "\" as a hash or hash reference!");
}
// Impossible (confirmed by Larry:
// http://www.nntp.perl.org/group/perl.perl6.language/22535)
// @foo := %bar, %bar := @foo
} else {
PIL2JS.die("Can't bind arrays to hashes or hashes to arrays!");
}
return this;
},
// Needed for "is copy".
copy: function () {
return new PIL2JS.Box(this.FETCH());
},
// Return us as a native JavaScript object.
toNative: function () {
var unboxed = this.FETCH();
// Special magic for Array: Call .toNative() for each element.
if(unboxed instanceof Array) {
var arr = [];
for(var i = 0; i < unboxed.length; i++) {
arr.push(unboxed[i] == undefined ? undefined : unboxed[i].toNative());
}
if(unboxed.flatten_me) arr.flatten_me = unboxed.flatten_me;
return arr;
} else if(unboxed instanceof PIL2JS.Hash) {
var hash = {};
for(var key in unboxed.entries) {
hash[key] = unboxed.entries[key].value.toNative();
}
return hash;
} else if(unboxed instanceof PIL2JS.Pair) {
var hash = {};
hash[unboxed.key.toNative()] = unboxed.value.toNative();
} else if(unboxed instanceof PIL2JS.NamedPair) {
PIL2JS.die("Can't .toNative() named pairs!");
// Special magic for Function: Create a wrapper function which wraps all
// arguments in PIL2JS.Boxes and unwraps the results.
// real_func :: BoxedArgs -> BoxedResults
// wrapper_func :: NativeArgs -> NativeResult
} else if(unboxed instanceof Function) {
return function () {
var args = []; //PIL2JS.Context.ItemAny.FETCH()].concat(arguments);
for(var i = 0; i < arguments.length; i++)
args[i] = new PIL2JS.Box.Constant(arguments[i]);
// Of course, this will break if unboxed does call/cc magic.
var retval = PIL2JS.cps2normal(unboxed, [PIL2JS.Context.ItemAny].concat(args));
if(retval == undefined)
retval = new PIL2JS.Box.Constant(undefined);
// PIL2JS.die("Continuation wasn't called!");
return retval.toNative();
};
} else if(unboxed instanceof Boolean) {
return unboxed == true ? true : false;
} else if(unboxed instanceof PIL2JS.Ref) {
return unboxed.referencee.toNative();
// Special magic for string: Work around IE bug.
} else if(typeof unboxed == "string") {
// Convert "\n"s (IE...)
return unboxed.replace(/\n/, PIL2JS.LF);
// Else: simply return the unboxed thing.
} else {
return unboxed;
}
}
};
// PIL2JS.Box.Proxy is the equivalent of Perl's Proxy class.
PIL2JS.Box.Proxy = function (fetch, store) {
this.FETCH = fetch;
this.STORE = store;
this.uid = PIL2JS.new_uid();
this.container_type = PIL2JS.container_type(fetch());
};
// new PIL2JS.Box.Readonly(some_existing_box) returns a new box which cannot be
// assigned to. Necessary for sub params without "is rw".
PIL2JS.Box.ReadOnly = function (box) {
this.FETCH = function () { return box.FETCH() };
this.STORE = function (n) { PIL2JS.die("Can't modify readonly item!"); return n };
this.uid = box.uid;
this.container_type = box.container_type;
};
// Returns a new box wrapping a constant value.
// Assignment and rebinding will, of course, not work.
PIL2JS.Box.Constant = function (value) {
this.FETCH = function () { return value };
this.STORE = function (n) { PIL2JS.die("Can't modify constant item!") };
this.BINDTO = function (o) { PIL2JS.die("Can't rebind constant item!") };
this.uid = undefined;
this.container_type = PIL2JS.container_type(value);
this.isConstant = true;
};
// Returns a stub box -- all calls will die.
PIL2JS.Box.Stub = function (value) {
this.FETCH = function () { PIL2JS.die(".FETCH() of a PIL2JS.Box.Stub called!") }
this.STORE = function (n) { PIL2JS.die(".STORE() of a PIL2JS.Box.Stub called!") };
this.BINDTO = function (o) { PIL2JS.die(".BINDTO() of a PIL2JS.Box.Stub called!") };
this.uid = function () { PIL2JS.die(".uid() of a PIL2JS.Box.Stub called!") };
this.container_type = PIL2JS.ContainerType.Scalar;
};
// Inheritance.
PIL2JS.Box.Proxy.prototype = PIL2JS.Box.prototype;
PIL2JS.Box.ReadOnly.prototype = PIL2JS.Box.prototype;
PIL2JS.Box.Constant.prototype = PIL2JS.Box.prototype;
PIL2JS.Box.Stub.prototype = PIL2JS.Box.prototype;
PIL2JS.Box.constant_func = function (arity, f) {
f.pil2js_arity = arity;
return new PIL2JS.Box.Constant(f);
};
PIL2JS.ContainerType = {
Scalar: { toString: function () { return "PIL2JS.ContainerType.Scalar" } },
Array: { toString: function () { return "PIL2JS.ContainerType.Array" } },
Hash: { toString: function () { return "PIL2JS.ContainerType.Hash" } }
};
PIL2JS.container_type = function (thing) {
if(thing == undefined) {
return PIL2JS.ContainerType.Scalar;
} else if(thing instanceof Array) {
return PIL2JS.ContainerType.Array;
} else if(thing instanceof PIL2JS.Hash) {
return PIL2JS.ContainerType.Hash;
} else {
return PIL2JS.ContainerType.Scalar;
}
}
PIL2JS.toPIL2JSBox = function (thing) {
// I'd do this as Object.prototype.toPIL2JSBox, but this causes severe
// problems, is a hack, and causes the MetaModel to not work, as it depends
// on for(var k in some_object) to not return "toPIL2JSBox".
if(thing == undefined) {
return new PIL2JS.Box.Constant(undefined);
} else if(thing instanceof Array) {
var ret = [];
for(var i = 0; i < thing.length; i++) {
ret.push(PIL2JS.toPIL2JSBox(thing[i]));
}
if(thing.flatten_me) ret.flatten_me = thing.flatten_me;
return new PIL2JS.Box.Constant(ret);
} else if(thing instanceof Function) {
return PIL2JS.Box.constant_func(thing.arity, function (args) {
PIL2JS.call(undefined, thing, args);
});
} else {
return new PIL2JS.Box.Constant(thing);
}
}
// Hack to work around JS not providing .tailcall... :(
PIL2JS.runloop = function (f) {
var was_in_errhandler = true;
while(was_in_errhandler) {
was_in_errhandler = false;
try { f() } catch(err) {
if(err instanceof Function) {
f = err;
was_in_errhandler = true;
} else {
throw err;
}
}
}
};
// Call (possibly native sub) sub with args
PIL2JS.call = function (inv, sub, args) {
if(sub == undefined)
PIL2JS.die("Use of uninitialized value in subroutine entry!");
// It's a plain sub (i.e. not method) call.
if(inv == undefined) {
// It's a boxed (and therefore Perl 6) sub.
if(sub.FETCH) {
sub.FETCH()(args);
} else {
var cxt = args.shift();
var cc = args.pop();
var code = "PIL2JS.toPIL2JSBox(sub(";
for(var i = 0; i < args.length; i++) {
code += "args[" + i + "].toNative(),";
}
if(args.length > 0) code = code.slice(0, -1);
code += "))";
cc(eval(code));
}
// It's a method call.
} else {
if(inv.FETCH) {
var val = inv.FETCH();
// Possibly autoderef Refs.
if(val instanceof PIL2JS.Ref && val.autoderef) val = val.referencee.FETCH();
// Check if we're calling a real object part of the MetaModel or
// something other.
var isreal = val instanceof Perl6.Instance
|| val instanceof Perl6.MetaClass
|| val instanceof Perl6.Method
|| val instanceof Perl6.Class;
// We're calling a method on a native JS object which belongs to us
// (Array, PIL2JS.Hash, etc.)?
if(!isreal) {
// So create an instance of the corresponding Perl 6 class (which is
// part of the metamodel).
var realclass = PIL2JS.nativeclass2realclass(
val == undefined
? undefined
: val.constructor
);
if(realclass) {
val = new Perl6.Instance(realclass.FETCH());
isreal = true;
}
}
// All classes we create inherit from __PIL2JS. This is so we can detect
// that our classes are really our's.
var isour = isreal && val.isa("__PIL2JS");
// It is a real object, but it doesn't belong to us: Cut off the context
// and inv info and call the method the official way.
if(isreal && !isour) {
var cc = args.pop();
cc(PIL2JS.Box.Constant(call_method.apply([val, sub].concat(args.slice(2)))));
// It is a real object and it belongs to us: Retrieve the original boxed
// sub object and call it.
} else if(isreal && isour && val.can(sub)) {
var boxedsub = val.can(sub).call("__i_am_pil2js");
boxedsub.FETCH()([args[0], inv].concat(args.slice(1)));
} else if(!isreal && !isour) {
if(val[sub] == undefined) {
PIL2JS.die("No such native method: \"" + sub + "\"");
}
if(val[sub] instanceof Function) {
// It's a method
return PIL2JS.call(undefined, val[sub], args);
} else {
// It's an attribute/whatever
var cc = args.pop();
cc(PIL2JS.toPIL2JSBox(val[sub]));
}
// Sorry.
} else {
PIL2JS.die("No such method: \"" + sub + "\"");
}
// It is a native JS object. Retrieve a Function reference and re-call
// PIL2JS.call, as a native JS method *is* allowd to be a boxed object (see
// e.g. Rul and Match).
} else {
return PIL2JS.call(undefined, inv[sub], args);
}
}
};
PIL2JS.__PIL2JSClass = new Perl6.Class("__PIL2JS", { "class": { "methods": {} } });
PIL2JS.new_empty_class = function (name, superclass) {
return new PIL2JS.Box.Constant(
new Perl6.Class(name, {
"is": [superclass.FETCH()],
"class": { "methods": {} }
})
);
}
var _3aMain_3a_3aAny = PIL2JS.new_empty_class("Any", new PIL2JS.Box.Constant(PIL2JS.__PIL2JSClass));
var _3aMain_3a_3aItem = PIL2JS.new_empty_class("Item", _3aMain_3a_3aAny);
var _3aMain_3a_3aArray = PIL2JS.new_empty_class("Array", _3aMain_3a_3aItem);
var _3aMain_3a_3aHash = PIL2JS.new_empty_class("Hash", _3aMain_3a_3aItem);
var _3aMain_3a_3aPair = PIL2JS.new_empty_class("Pair", _3aMain_3a_3aItem);
var _3aMain_3a_3aStr = PIL2JS.new_empty_class("Str", _3aMain_3a_3aItem);
var _3aMain_3a_3aNum = PIL2JS.new_empty_class("Num", _3aMain_3a_3aItem);
var _3aMain_3a_3aInt = PIL2JS.new_empty_class("Int", _3aMain_3a_3aNum);
var _3aMain_3a_3aRat = PIL2JS.new_empty_class("Rat", _3aMain_3a_3aNum);
var _3aMain_3a_3aBool = PIL2JS.new_empty_class("Bool", _3aMain_3a_3aItem);
var _3aMain_3a_3aCode = PIL2JS.new_empty_class("Code", _3aMain_3a_3aItem);
var _3aMain_3a_3aBlock = PIL2JS.new_empty_class("Block", _3aMain_3a_3aCode);
var _3aMain_3a_3aRoutine = PIL2JS.new_empty_class("Routine", _3aMain_3a_3aCode);
var _3aMain_3a_3aSub = PIL2JS.new_empty_class("Sub", _3aMain_3a_3aRoutine);
var _3aMain_3a_3aMethod = PIL2JS.new_empty_class("Method", _3aMain_3a_3aRoutine);
var _3aMain_3a_3aSubmethod = PIL2JS.new_empty_class("Submethod", _3aMain_3a_3aRoutine);
var _3aMain_3a_3aMulti = PIL2JS.new_empty_class("Multi", _3aMain_3a_3aRoutine);
var _3aMain_3a_3aRule = PIL2JS.new_empty_class("Rule", _3aMain_3a_3aRoutine);
var _3aMain_3a_3aMacro = PIL2JS.new_empty_class("Macro", _3aMain_3a_3aRoutine);
var _3aMain_3a_3aRef = PIL2JS.new_empty_class("Ref", _3aMain_3a_3aItem);
var _3aMain_3a_3aJunction = PIL2JS.new_empty_class("Junction", _3aMain_3a_3aAny);
var _3aMain_3a_3aRul = PIL2JS.new_empty_class("Rul", _3aMain_3a_3aItem);
var _3aMain_3a_3aMatch = PIL2JS.new_empty_class("Match", _3aMain_3a_3aItem);
// Returns, given a native JS object, the corresponding boxed class object.
PIL2JS.nativeclass2realclass = function (constr) {
if(constr == Array) {
return _3aMain_3a_3aArray;
} else if(constr == PIL2JS.Hash) {
return _3aMain_3a_3aHash;
} else if(constr == PIL2JS.Pair) {
return _3aMain_3a_3aPair;
} else if(constr == PIL2JS.NamedPair) {
PIL2JS.die("A named pair leaked into PIL2JS.nativeclass2realclass!");
} else if(constr == String) {
return _3aMain_3a_3aStr;
} else if(constr == Number) {
return _3aMain_3a_3aNum;
} else if(constr == Boolean) {
return _3aMain_3a_3aBool;
} else if(constr == Function) {
return _3aMain_3a_3aCode;
} else if(constr == PIL2JS.Junction.Any || constr == PIL2JS.Junction.All || constr == PIL2JS.Junction.One || constr == PIL2JS.Junction.None) {
return _3aMain_3a_3aJunction;
} else if(constr == PIL2JS.Ref) {
return _3aMain_3a_3aRef;
} else if(constr == PIL2JS.Match) {
return _3aMain_3a_3aMatch;
} else if(constr == PIL2JS.Rul) {
return _3aMain_3a_3aRul;
} else if(constr == undefined) {
return _3aMain_3a_3aItem;
}
};
// Adds a method to a boxed class object.
PIL2JS.addmethod = function (cls, name, sub) {
if(cls == undefined) PIL2JS.die("PIL2JS.addmethod called with undefined class!");
cls = cls.FETCH();
if(!(cls instanceof Perl6.Class))
PIL2JS.die("PIL2JS.addmethod called with a weird class: \"" + cls + "\"!");
cls.meta().add_method(name, new Perl6.Method(cls.meta(), function (check) {
if(check != "__i_am_pil2js")
PIL2JS.die("PIL2JS method called from outside of PIL2JS!");
return sub;
})); //, sub.FETCH().pil2js_arity);
};
// Flatten inp_arr (one level):
// [1,2,[3,4,5],[6,[7,8]]] -> [1,2,3,4,5,6,[7,8]]
PIL2JS.make_slurpy_array = function (inp_arr) {
var out_arr = [];
for(var i = 0; i < inp_arr.length; i++) {
if(inp_arr[i].FETCH() instanceof Array) {
add_arr = [];
for(var j = 0; j < inp_arr[i].FETCH().length; j++) {
add_arr.push(
inp_arr[i].FETCH()[j] == undefined
? new PIL2JS.Box.Constant(undefined)
: inp_arr[i].FETCH()[j]
);
}
out_arr = out_arr.concat(add_arr);
} else if(inp_arr[i].FETCH() instanceof PIL2JS.Hash) {
var pairs = inp_arr[i].FETCH().pairs();
for(var i = 0; i < pairs.length; i++) {
pairs[i] = new PIL2JS.Box.Constant(pairs[i]);
}
out_arr = out_arr.concat(pairs);
} else {
out_arr.push(inp_arr[i]);
}
}
return out_arr;
};
// StubIO class.
PIL2JS.StubIO = function () {};
PIL2JS.StubIO.prototype.print = new PIL2JS.Box.Constant(function (args) {
_26Main_3a_3aprint.FETCH()(args);
});
PIL2JS.StubIO.prototype.say = new PIL2JS.Box.Constant(function (args) {
_26Main_3a_3asay.FETCH()(args);
});
// Rul class.
PIL2JS.Rul = function (matcher) { this.matcher = matcher };
// Match class.
PIL2JS.Match = function (ok, from, to, str, subpos, subnamed) {
this.ok = ok;
this.from = from;
this.to = to;
this.str = str;
this.subpos = subpos;
this.subnamed = subnamed;
};
// Magical variables: $?POSITION, $!, etc.
var _24Main_3a_3a_3fPOSITION = new PIL2JS.Box("<unknown>");
var _24Main_3a_3a_3fSUBNAME = new PIL2JS.Box(undefined);
var _24Main_3a_3a_21 = new PIL2JS.Box(undefined);
var _25Main_3a_3aENV = new PIL2JS.Box(new PIL2JS.Hash);
var _40Main_3a_3a_2aEND = new PIL2JS.Box([]);
var _24Main_3a_3a_2aERR = new PIL2JS.StubIO;
var _24Main_3a_3aERR = _24Main_3a_3a_2aERR;
var _24Main_3a_3a_2aOUT = new PIL2JS.StubIO;
var _24Main_3a_3aOUT = _24Main_3a_3a_2aOUT;
var _24Main_3a_3a_2aPUGS_HAS_HSPLUGINS = new PIL2JS.Box.Constant(0);
var _24Main_3a_3aPUGS_HAS_HSPLUGINS = _24Main_3a_3a_2aPUGS_HAS_HSPLUGINS;
var _40Main_3a_3a_2aINC = new PIL2JS.Box([]);
var _26Main_3a_3a_3fBLOCK = new PIL2JS.Box(undefined);
var _26Main_3a_3a_3fSUB = new PIL2JS.Box(undefined);
var _24Main_3a_3a_3fOS = new PIL2JS.Box.Constant("unknown"); // XXX
var _24Main_3a_3a_2aOS = new PIL2JS.Box.Constant(Perl5 ? Perl5.perl_eval('$^O') : "browser");
var _24Main_3a_3aOS = _24Main_3a_3a_2aOS;
var _24Main_3a_3a_2aPID = new PIL2JS.Box.Constant(Perl5 ? Perl5.perl_eval('$$') : "unknown");
var _24Main_3a_3aPID = _24Main_3a_3a_2aPID;
var _24Main_3a_3a_3fPUGS_BACKEND = new PIL2JS.Box.Constant("BACKEND_JAVASCRIPT");
var _24Main_3a_3a_ = new PIL2JS.Box(undefined);
// $/ -- XXX WRONG needs to be lexical
var _24Main_3a_3a_2f = new PIL2JS.Box(undefined);
// Stub for $?CALLER::CALLER::POSITION, so Test.pm doesn't die on a failed
// test.
var _24_3fCALLER_3a_3aCALLER_3a_3aCALLER_3a_3aPOSITION =
new PIL2JS.Box("<$?CALLER::CALLER::POSITION not yet implemented>");
var _24_3fCALLER_3a_3aCALLER_3a_3aSUBNAME =
new PIL2JS.Box("<$?CALLER::CALLER::SUBNAME not yet implemented>");
// HACKS. Needs prober integration of Perl6.MetaModel.
// XXX evil hack around %FooPackage::EXPORTS. See PIL::PVar, lines 34f.
var _25PIL2JS_3a_3aEXPORTS_DUMMY_VARIABLE = new PIL2JS.Box(new PIL2JS.Hash);
// Prettyprint an error msg.
PIL2JS.new_error = function (msg) {
if(!(msg instanceof PIL2JS.Box)) msg = new PIL2JS.Box.Constant(msg);
var errmsg = typeof(msg.FETCH()) == "string" || msg.FETCH() instanceof String
? msg.FETCH()
: "<obj>";
var err = new Error(errmsg.slice(-1, 1) == "\n"
? errmsg
: errmsg + " at " + _24Main_3a_3a_3fPOSITION.toNative()
);
err.pil2js_orig_msg = msg;
err.pil2js_pos = _24Main_3a_3a_3fPOSITION.toNative();
return err;
};
// &warn and &die.
PIL2JS.warn = function (msg) { PIL2JS.print_exception(PIL2JS.new_error(msg)) };
PIL2JS.die = function (msg) {
var error = PIL2JS.new_error(msg);
throw(error);
};
// &return, &leave, &last, &next are all implemented using faked escape
// continuations, i.e. exceptions.
PIL2JS.ControlException = {};
PIL2JS.ControlException.last = function () {};
PIL2JS.ControlException.last.prototype.toString =
function () { return "Can't \"last\" outside a loop block!" };
PIL2JS.ControlException.next = function () {};
PIL2JS.ControlException.next.prototype.toString =
function () { return "Can't \"next\" outside a loop block!" };
PIL2JS.ControlException.redo = function () {};
PIL2JS.ControlException.redo.prototype.toString =
function () { return "Can't \"redo\" outside a loop block!" };
PIL2JS.ControlException.end = function () {};
// PIL2JS.generic_return -- generates a function, which, when invoked, will
// cause a return of the given level by throwing an appropriate exception.
PIL2JS.generic_return = function (returncc) {
return new PIL2JS.Box.Constant(function (args) {
var cxt = args.shift(), cc = args.pop();
// args = PIL2JS.make_slurpy_array(args);
var ret =
args.length > 1 ? new PIL2JS.Box.Constant(args) :
args.length == 1 ? args[0] :
new PIL2JS.Box.Constant(undefined);
returncc(ret, cc);
});
};
// Entrypoints for currently active coroutines
PIL2JS.coro_entrypoints = [];
PIL2JS.already_exited = false;
var _26Main_3a_3aexit = new PIL2JS.Box(PIL2JS.Box.constant_func(1, function (args) {
if(PIL2JS.already_exited) return;
PIL2JS.already_exited = true;
// Run all END blocks.
var blocks = _40Main_3a_3a_2aEND.FETCH();
for(var i = 0; i < blocks.length; i++) {
PIL2JS.cps2normal(blocks[i].FETCH(), [PIL2JS.Context.Void]);
}
/* We've finished, so we don't call the cc. */
throw new PIL2JS.ControlException.end;
}).FETCH());
// Array of boxed subs we're currently in.
var PIL2JS_callchain = [];
// Array of pads we're currently in, used for $CALLER::.
// Note that the pads change at runtime, i.e.:
// # No my $a yet
// # PIL2JS_subpads[-1]["$a"] undefined
// my $a;
// # PIL2JS_subpads[-1]["$a"] is defined now.
var PIL2JS_subpads = [];
PIL2JS.resolve_callervar = function (delta, name) {
// delta == 0: current pad
// delta == 1: pad of calling sub ($CALLER::foo)
// delta == 2: pad of the sub calling the calling sub ($CALLER::CALLER::foo)
// etc.
if(PIL2JS_subpads.length >= delta + 1) {
var pad = PIL2JS_subpads[PIL2JS_subpads.length - delta - 1];
if(pad[name]) {
return pad[name];
} else {
PIL2JS.die("No variable named \"" + name + "\" in caller[" + delta + "]!");
}
} else {
PIL2JS.die("No caller[" + delta + "] found!");
}
};
// Greps args for PIL2JS.NamedPairs and returns them as a hash.
PIL2JS.grep_for_namedpairs = function (args) {
var pairs = {};
for(var i = 0; i < args.length; i++) {
if(args[i].FETCH() instanceof PIL2JS.NamedPair) {
pairs[args[i].FETCH().key] = args[i].FETCH().value;
}
}
return pairs;
};
PIL2JS.get_and_remove_all_namedpairs = function (args) {
var hash = new PIL2JS.Hash;
var new_args = [];
for(var i = 0; i < args.length; i++) {
if(args[i].FETCH() instanceof PIL2JS.NamedPair) {
var pair = new PIL2JS.Pair(
(new PIL2JS.Box.Constant(args[i].FETCH().key)),
args[i].FETCH().value
);
hash.add_pair(pair);
} else {
new_args.push(args[i]);
}
}
return { args: new_args, hash: hash };
}
// *@foo sets @foo's .flatten_me property to true.
// Here, we expand these flattened arrays.
PIL2JS.possibly_flatten = function (args) {
var ret = [];
for(var i = 0; i < args.length; i++) {
if(args[i].FETCH() instanceof Array && args[i].FETCH().flatten_me) {
var add_arr = [];
for(var j = 0; j < args[i].FETCH().length; j++) {
add_arr.push(
args[i].FETCH()[j] == undefined
? new PIL2JS.Box.Constant(undefined)
: args[i].FETCH()[j]
);
}
ret = ret.concat(add_arr);
} else if(args[i].FETCH() instanceof PIL2JS.Hash && args[i].FETCH().flatten_me) {
var pairs = args[i].FETCH().pairs();
for(var j = 0; j < pairs.length; j++) {
var named = new PIL2JS.NamedPair(
pairs[j].key.toNative(),
pairs[j].value
);
pairs[j] = new PIL2JS.Box.Constant(named);
}
ret = ret.concat(pairs);
} else {
ret.push(args[i]);
}
}
return ret;
};
// Searches args for pairs and deletes the pairs where .key eq name.
PIL2JS.delete_namedpair_from_args = function (args, name) {
var n = [];
for(var i = 0; i < args.length; i++) {
if(!(args[i].FETCH() instanceof PIL2JS.NamedPair && args[i].FETCH().key == name)) {
n.push(args[i]);
}
}
return n;
};
// Context class.
PIL2JS.Context = function (cxt) {
this["main"] = cxt["main"];
this["type"] = cxt["type"];
return this;
};
PIL2JS.Context.prototype.toString = function () {
return "Context.new(:main[" + this["main"] + "], :type[" + this["type"] + "])";
};
PIL2JS.Context.Void = new PIL2JS.Context({ main: "void" });
PIL2JS.Context.ItemAny = new PIL2JS.Context({ main: "item", type: "Any" });
PIL2JS.Context.SlurpyAny = new PIL2JS.Context({ main: "slurpy", type: "Any" });
PIL2JS.print_exception = function (err) {
PIL2JS.cps2normal(
_26Main_3a_3asay.FETCH(), [
PIL2JS.Context.Void,
PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_7e.FETCH(), [
PIL2JS.Context.ItemAny,
//err.pil2js_orig_msg
// ? err.pil2js_orig_msg :
new PIL2JS.Box.Constant(err.toString())
])
]
);
};
PIL2JS.catch_all_exceptions = function (code) {
try { code() } catch(err) {
PIL2JS.print_exception(err);
}
};
PIL2JS.catch_end_exception = function (code) {
try { code() } catch(err) {
if(err instanceof PIL2JS.ControlException.end) {
return;
} else {
throw err;
}
}
};
// Will, of course, break when call/cc magic is done.
PIL2JS.cps2normal = function (f, args) {
var ret = undefined;
PIL2JS.runloop(function () { f(args.concat(function (r) { ret = r })) });
//if(ret == undefined) PIL2JS.die("Continuation wasn't called[" + f + "]!");
return ret;
};
// &*ref.
var _26Main_3a_3aref = PIL2JS.Box.constant_func(1, function (args) {
var thing = args[1].FETCH();
var cc = args.pop();
if(thing != undefined && thing.referencee && thing.autoderef) thing = thing.referencee.FETCH();
if(thing == undefined) {
cc(new PIL2JS.Box.Constant("Scalar")); // XXX?
} else if(typeof(thing) == "string" || thing instanceof String) {
cc(new PIL2JS.Box.Constant("Str"));
} else if(typeof(thing) == "boolean" || thing instanceof Boolean) {
cc(new PIL2JS.Box.Constant("Bool"));
} else if(typeof(thing) == "number" || thing instanceof Number) {
cc(new PIL2JS.Box.Constant("Num"));
} else if(thing instanceof Array) {
cc(new PIL2JS.Box.Constant("Array"));
} else if(thing instanceof PIL2JS.Hash) {
cc(new PIL2JS.Box.Constant("Hash"));
} else if(thing instanceof PIL2JS.Pair) {
cc(new PIL2JS.Box.Constant("Pair"));
} else if(thing instanceof Function) {
cc(new PIL2JS.Box.Constant("Code"));
} else if(thing instanceof PIL2JS.Ref) {
cc(new PIL2JS.Box.Constant("Ref"));
} else if(thing instanceof PIL2JS.Junction.Any || thing instanceof PIL2JS.Junction.All || thing instanceof PIL2JS.Junction.One || thing instanceof PIL2JS.Junction.None) {
cc(new PIL2JS.Box.Constant("Junction"));
} else if(thing instanceof Perl6.Class) {
cc(new PIL2JS.Box.Constant("Class")); // XXX
} else if(thing instanceof PIL2JS.Rul) {
cc(new PIL2JS.Box.Constant("Rul"));
} else if(thing instanceof PIL2JS.Match) {
cc(new PIL2JS.Box.Constant("Match"));
} else {
PIL2JS.die(
"Internal error: .WHAT() not yet implemented for " +
typeof(thing) +
" (constructor: " + thing.constructor + ", value: " + thing + ")"
);
}
});
_26Main_3a_3aref.perl_name = "&Main::WHAT";
PIL2JS.addmethod(_3aMain_3a_3aAny, "WHAT", _26Main_3a_3aref);
// &*isa. hack.
var _26Main_3a_3aisa = PIL2JS.Box.constant_func(1, function (args) {
args.shift(); // cxt
var self = args.shift(),
cmptype = args.shift().FETCH();
cc = args.pop(),
ref = _26Main_3a_3aref;
if(args.length > 0) {
PIL2JS.die("Too many arguments passed to &isa!");
}
// XXX wrong
if(cmptype instanceof Perl6.Class) {
cmptype = cmptype.meta().name();
}
ref.FETCH()([PIL2JS.Context.ItemAny, self, function (type) {
type = type.FETCH();
cc(new PIL2JS.Box.Constant(
type == cmptype ||
type == "Array" && cmptype == "List" ||
// Hacks:
type == "Num" && cmptype == "Int" ||
type == "Num" && cmptype == "Rat" ||
type == "Code" && cmptype == "Block" ||
type == "Code" && cmptype == "Sub" ||
type == "Any"
));
}]);
});
_26Main_3a_3aisa.perl_name = "&Main::isa";
PIL2JS.addmethod(_3aMain_3a_3aAny, "isa", _26Main_3a_3aisa);
// &prefix:<\>
var _26Main_3a_3aprefix_3a_5c = PIL2JS.Box.constant_func(1, function (args) {
var thing = args[1], cc = args.pop();
cc(new PIL2JS.Box.Constant(new PIL2JS.Ref(thing)));
});
_26Main_3a_3aprefix_3a_5c.perl_name = "&Main::prefix:\\";
// &prefix:<~>. Written in JS instead of P6 for speed, as &prefix:<~> gets
// called often.
var _26Main_3a_3aprefix_3a_7e = PIL2JS.Box.constant_func(1, function (args) {
var thing = args[1].FETCH(), cc = args.pop();
if(thing == undefined) {
cc(new PIL2JS.Box.Constant(""));
} else {
_26Main_3a_3aref.FETCH()([PIL2JS.Context.ItemAny, args[1], function (ref) {
ref = ref.FETCH();
if(thing != undefined && thing.referencee && thing.autoderef) thing = thing.referencee.FETCH();
if(ref == "Str") {
cc(new PIL2JS.Box.Constant(String(thing).toString()));
} else if(ref == "Array") {
var res = "";
for(var i = 0; i < thing.length; i++) {
if(thing[i] != undefined) {
res += PIL2JS.cps2normal(
_26Main_3a_3aprefix_3a_7e.FETCH(), [PIL2JS.Context.ItemAny, thing[i]]
).FETCH();
}
res += " ";
}
if(thing.length > 0) res = res.slice(0, -1);
cc(new PIL2JS.Box.Constant(res));
} else if(ref == "Hash") {
var res = "";
var pairs = thing.pairs();
for(var i = 0; i < pairs.length; i++) {
res += "" +
PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_7e.FETCH(), [PIL2JS.Context.ItemAny, pairs[i].key]).FETCH() +
"\t" +
PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_7e.FETCH(), [PIL2JS.Context.ItemAny, pairs[i].value]).FETCH() +
"\n";
}
if(pairs.length > 0) res = res.slice(0, -1);
cc(new PIL2JS.Box.Constant(res));
} else if(ref == "Pair") {
cc(new PIL2JS.Box.Constant(
"" +
PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_7e.FETCH(), [PIL2JS.Context.ItemAny, thing.key]).FETCH() +
"\t" +
PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_7e.FETCH(), [PIL2JS.Context.ItemAny, thing.value]).FETCH()
));
} else if(ref == "Bool") {
cc(new PIL2JS.Box.Constant(
PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_3f.FETCH(), [PIL2JS.Context.ItemAny, args[1]]).FETCH()
? "1"
: ""
));
} else if(ref == "Num") {
var num2str = function (num) {
if(num == Infinity) return "Inf";
if(num == -Infinity) return "-Inf";
if(num == num) return num.toString();
return NaN;
};
cc(new PIL2JS.Box.Constant(num2str(thing)));
} else if(ref == "Junction") {
var res = "", values = thing.values;
for(var i = 0; i < values.length; i++) {
res += PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_7e.FETCH(), [PIL2JS.Context.ItemAny, values[i]]).FETCH();
res += thing.op;
}
if(values.length > 0) res = res.slice(0, -thing.op.length);
cc(new PIL2JS.Box.Constant(res));
} else if(ref == "Ref") {
PIL2JS.die("Can't stringify non-array or hash references!");
} else if(ref == "Class") { // XXX
cc(new PIL2JS.Box.Constant(thing.meta().name()));
} else if(ref == "Match") {
cc(new PIL2JS.Box.Constant(thing.str));
} else {
PIL2JS.die(
"Stringification for objects of class " +
ref +
" not yet implemented!"
);
}
}]);
}
});
// &prefix:<+>. Written in JS instead of P6 for speed, as it gets called often.
var _26Main_3a_3aprefix_3a_2b = PIL2JS.Box.constant_func(1, function (args) {
var cc = args.pop();
PIL2JS.possibly_autothread([args[1]], [true], cc, function (cc, thing) {
var ref = PIL2JS.cps2normal(_26Main_3a_3aref.FETCH(), [PIL2JS.Context.ItemAny, thing]).FETCH();
var unboxed = thing.FETCH();
if(unboxed == undefined) return cc(new PIL2JS.Box.Constant(0));
if(unboxed.referencee && unboxed.autoderef) unboxed = unboxed.referencee.FETCH();
if(unboxed == undefined) return cc(new PIL2JS.Box.Constant(0));
var str2num = function (str) {
if(Number(str) == Number(str)) {
return Number(str);
} else {
// JavaScript's Number couldn't parse str (Number(str) returned NaN)
str = str.replace(/\s+$/, "");
if(str == "Inf") return Infinity;
if(str == "-Inf") return -Infinity;
if(str == "NaN") return NaN;
if(str.substr(0,2) == "0d") return str2num(str.substring(2));
if(str.substr(0,2) == "0b") return parseInt(str.substring(2), 2);
if(str.substr(0,2) == "0o") return parseInt(str.substring(2), 8);
if(Number(str) == Number(str)) return Number(str);
return 0;
}
};
if(ref == "Str") {
cc(new PIL2JS.Box.Constant(str2num(unboxed)));
} else if(ref == "Array") {
cc(new PIL2JS.Box.Constant(unboxed.length));
} else if(ref == "Hash") {
cc(new PIL2JS.Box.Constant(unboxed.num_of_entries));
} else if(ref == "Bool") {
cc(new PIL2JS.Box.Constant(
PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_3f.FETCH(), [PIL2JS.Context.ItemAny, thing]).FETCH()
? 1
: 0
));
} else if(ref == "Num") {
cc(new PIL2JS.Box.Constant(Number(unboxed)));
} else if(ref == "Ref") {
PIL2JS.die("Can't numfiy non-array or hash references!");
} else if(ref == "Match") {
cc(new PIL2JS.Box.Constant(str2num(thing.str)));
} else {
PIL2JS.die(
"Numification for objects of class "+
ref +
" not yet implemented!"
);
}
});
});
// &prefix:<?>. Written in JS instead of P6 for speed, as it gets called very
// often.
var _26Main_3a_3aprefix_3a_3f = PIL2JS.Box.constant_func(1, function (args) {
var a = args[1].FETCH(), cc = args.pop();
if(a instanceof PIL2JS.Ref && a.autoderef) a = a.referencee.FETCH();
if(a instanceof Array) {
cc(new PIL2JS.Box.Constant(a.length > 0));
} else if(a instanceof PIL2JS.Hash) {
cc(new PIL2JS.Box.Constant(a.num_of_entries > 0));
} else if(a instanceof PIL2JS.Ref) {
cc(new PIL2JS.Box.Constant(1 == 1));
} else if(a instanceof PIL2JS.Match) {
cc(new PIL2JS.Box.Constant(a.ok));
} else if(a instanceof PIL2JS.Junction.All) {
for(var i = 0; i < a.values.length; i++) {
if(!PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_3f.FETCH(), [PIL2JS.Context.ItemAny, a.values[i]]).FETCH()) {
return cc(new PIL2JS.Box.Constant(0 == 1));
}
}
cc(new PIL2JS.Box.Constant(1 == 1));
} else if(a instanceof PIL2JS.Junction.Any) {
for(var i = 0; i < a.values.length; i++) {
if(PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_3f.FETCH(), [PIL2JS.Context.ItemAny, a.values[i]]).FETCH()) {
return cc(new PIL2JS.Box.Constant(1 == 1));
}
}
cc(new PIL2JS.Box.Constant(0 == 1));
} else if(a instanceof PIL2JS.Junction.One) {
var ret = false;
for(var i = 0; i < a.values.length; i++) {
if(PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_3f.FETCH(), [PIL2JS.Context.ItemAny, a.values[i]]).FETCH()) {
if(ret) {
return cc(new PIL2JS.Box.Constant(0 == 1));
} else {
ret = true;
}
}
}
cc(new PIL2JS.Box.Constant(ret));
} else if(a instanceof PIL2JS.Junction.None) {
for(var i = 0; i < a.values.length; i++) {
if(PIL2JS.cps2normal(_26Main_3a_3aprefix_3a_3f.FETCH(), [PIL2JS.Context.ItemAny, a.values[i]]).FETCH()) {
return cc(new PIL2JS.Box.Constant(0 == 1));
}
}
cc(new PIL2JS.Box.Constant(1 == 1));
} else {
cc(new PIL2JS.Box.Constant(a != undefined && a != "" && a != "0" && a != 0));
}
});
/*PIL2JS.bind_params = function (pdefs, args, sub) {
var cxt = args.shift();
args = PIL2JS.possibly_flatten(args);
var pairs = PIL2JS.grep_for_namedpairs(args);
// Phase 1: Possibly remove and extract named args.
for(var i = 0; i < pdefs.length; i++) {
if(pairs[pdefs[i].name] != undefined) {
pdefs[i].result = pdefs[i].undef.BINDTO(pairs[pdefs[i].name]);
args = PIL2JS.delete_pair_from_args(args, pdefs[i].name);
}
}
}*/
PIL2JS.Junction = {};
PIL2JS.Junction.All = function (values) { this.values = values; this.op = "&" };
PIL2JS.Junction.Any = function (values) { this.values = values; this.op = "|" };
PIL2JS.Junction.None = function (values) { this.values = values; this.op = "none" };
PIL2JS.Junction.One = function (values) { this.values = values; this.op = "^" };
PIL2JS.possibly_autothread = function (args, bools, origcc, sub) {
args = [].concat(args);
// First pass: Autothread all and none.
// Second pass: Autothread any and one.
for(var pass = 0; pass <= 1; pass++) {
for(var i = 0; i < args.length; i++) {
if(args[i] != undefined && bools[i]) {
var junc = args[i].FETCH();
var autothread = pass == 0
? junc instanceof PIL2JS.Junction.All || junc instanceof PIL2JS.Junction.None
: junc instanceof PIL2JS.Junction.Any || junc instanceof PIL2JS.Junction.One;
if(autothread) {
var values = [].concat(junc.values);
var results = [];
var j = 0;
var cc = function (ret) {
if(ret != undefined) results.push(ret);
if(j < values.length) {
args[i] = values[j];
j++;
PIL2JS.possibly_autothread(args, bools, cc, sub);
} else {
origcc(new PIL2JS.Box.Constant(new junc.constructor(results)));
}
};
return cc();
}
}
}
}
sub.apply(null, [origcc].concat(args));
};