MethodParameter() public méthode

public MethodParameter ( int index ) : ExprVarParameter
index int
Résultat ExprVarParameter
 public static Stmt Atan2(Ctx ctx) {
     var arg0 = ctx.MethodParameter(0);
     var arg1 = ctx.MethodParameter(1);
     var eg = ctx.ExprGen;
     return new StmtReturn(ctx,
         new ExprTernary(ctx,
             eg.And(
                 eg.Not(new ExprJsResolvedMethod(ctx, ctx.Boolean, null, "Number.isFinite", arg0)),
                 eg.Not(new ExprJsResolvedMethod(ctx, ctx.Boolean, null, "Number.isFinite", arg1))
             ),
             ctx.Literal(Double.NaN),
             new ExprJsResolvedMethod(ctx, ctx.Double, null, "Math.atan2", arg0, arg1)
         )
     );
 }
 public static Stmt IsWhiteSpace(Ctx ctx) {
     // See http://msdn.microsoft.com/en-us/library/t809ektx.aspx for list
     var whiteSpace = " \u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d\u0085\u00a0";
     var arg0 = ctx.MethodParameter(0);
     var c = new ExprJsResolvedMethod(ctx, ctx.String, null, "String.fromCharCode", arg0);
     var indexOf = new ExprJsResolvedMethod(ctx, ctx.Boolean, ctx.Literal(whiteSpace), "indexOf", c);
     return new StmtReturn(ctx,
         new ExprBinary(ctx, BinaryOp.GreaterThanOrEqual, ctx.Boolean, indexOf, ctx.Literal(0)));
 }
            public Stmt GetImpl(Ctx ctx) {
                var a = ctx.MethodParameter(0, "a");
                var b = ctx.MethodParameter(1, "b");
                var hi = ctx.Local(ctx.UInt64, "hi");
                var lo = ctx.Local(ctx.UInt64, "lo");
                var limit = ctx.Literal(0x100000000UL, ctx._UInt64, "limit");
                var js = @"
hi = a[0] - b[0];
lo = a[1] - b[1];
if (lo < 0) {
    lo += limit;
    hi--;
}
if (hi < 0) hi += limit;
return [hi, lo];
";
                var stmt = new StmtJsExplicit(ctx, js, a, b, hi, lo, limit);
                return stmt;
            }
            public Stmt GetImpl(Ctx ctx) {
                var a = ctx.MethodParameter(0).Named("a");
                var b = ctx.MethodParameter(1).Named("b");
                var hi = ctx.Local(ctx.UInt64, "hi");
                var lo = ctx.Local(ctx.UInt64, "lo");
                var limit = ctx.Literal(0x100000000UL, ctx._UInt64, "limit");
                var js = @"
hi = a[0] + b[0];
lo = a[1] + b[1];
if (lo >= limit) {
    lo -= limit;
    hi++;
}
if (hi >= limit) hi -= limit;
return [hi, lo];
";
                var stmt = new StmtJsExplicit(ctx, js, a, b, hi, lo, limit);
                return stmt;
            }
            public Stmt GetImpl(Ctx ctx) {
                var a = ctx.MethodParameter(0, "a");
                var b = ctx.MethodParameter(1, "b");
                var aa = ctx.Local(ctx.Int32.MakeArray(), "aa");
                var bb = ctx.Local(ctx.Int32.MakeArray(), "bb");
                var ia = ctx.Local(ctx.Int32, "ia");
                var ib = ctx.Local(ctx.Int32, "ib");
                var mul = ctx.Local(ctx.Int32, "mul");
                var add = ctx.Local(ctx.Int32, "add");
                var mulCarry = ctx.Local(ctx.Int32, "mulCarry");
                var addCarry = ctx.Local(ctx.Int32, "addCarry");
                var rrOfs = ctx.Local(ctx.Int32, "rrOfs");
                var rr = ctx.Local(ctx.Int32.MakeArray(), "rr");
                var mask = ctx.Literal(0xffff, ctx.Int32, "mask");
                var limit = ctx.Literal(0x10000, ctx.Int32, "limit");
                var js = @"
aa = [a[0] >>> 16, a[0] & mask, a[1] >>> 16, a[1] & mask];
bb = [b[0] >>> 16, b[0] & mask, b[1] >>> 16, b[1] & mask];
rr = [0, 0, 0, 0];
for (ib = 3; ib >= 0; ib--) {
    mulCarry = 0;
    addCarry = 0;
    for(ia = 3; ia >= 3 - ib; ia--) {
        rrOfs = ia + ib - 3;
        mul = aa[ia] * bb[ib] + mulCarry;
        mulCarry = mul >>> 16;
        add = rr[rrOfs] + (mul & mask) + addCarry;
        if (add >= limit){
            rr[rrOfs] = add - limit;
            addCarry = 1;
        } else {
            rr[rrOfs] = add;
            addCarry = 0;
        }
    }
}
return [rr[1] + rr[0] * limit, rr[3] + rr[2] * limit];
";
                var stmt = new StmtJsExplicit(ctx, js, a, b, aa, bb, rr, mask, limit, ia, ib, mul, add, mulCarry, addCarry, rrOfs);
                return stmt;
            }
 public static Stmt Abs(Ctx ctx) {
     var arg = ctx.MethodParameter(0);
     ExprLiteral minVal;
     switch (arg.Type.MetadataType) {
     case MetadataType.SByte: minVal = ctx.Literal(Int8.MinValue); break;
     case MetadataType.Int16: minVal = ctx.Literal(Int16.MinValue); break;
     case MetadataType.Int32: minVal = ctx.Literal(Int32.MinValue); break;
     case MetadataType.Int64: minVal = ctx.Literal(Int64.MinValue); break;
     default: throw new InvalidOperationException("Cannot handle: " + arg.Type);
     }
     var exCtor = ctx.Module.Import(typeof(OverflowException).GetConstructor(Type.EmptyTypes));
     return new StmtIf(ctx,
         ctx.ExprGen.Equal(arg, minVal),
         new StmtThrow(ctx, new ExprNewObj(ctx, exCtor)),
         new StmtReturn(ctx,
             arg.Type.IsInt64() ?
             (Expr)new ExprCall(ctx, (Func<Int64, Int64>)_Int64.Abs, null, arg) :
             (Expr)new ExprJsResolvedMethod(ctx, arg.Type, null, "Math.abs", arg))
         );
 }
 public Stmt GetImpl(Ctx ctx) {
     var a = ctx.MethodParameter(0);
     var b = ctx.MethodParameter(1);
     var divMod = new ExprCall(ctx, (Func<UInt64, UInt64, object>)_Int64UInt64.UInt64DivRem, null, a, b).Named("divMod");
     var js = "return divMod[1];";
     var stmt = new StmtJsExplicit(ctx, js, divMod);
     return stmt;
 }
 public static Stmt ToString(Ctx ctx) {
     var value = ctx.This;
     var format = ctx.MethodParameter(0);
     var provider = ctx.MethodParameter(1);
     var nfi = ctx.Literal(null, ctx.Module.Import(typeof(NumberFormatInfo)));
     var expr = new ExprCall(ctx, (Func<Int64, string, NumberFormatInfo, string>)Cil2Js.JsResolvers.Classes.Helpers.Number.FormatInt64, null, value, format, nfi);
     return new StmtReturn(ctx, expr);
 }
        public static Stmt Decode(Ctx ctx) {
            var arg = ctx.MethodParameter(0, "arg");
            var objs = ctx.Local(ctx.Object, "objs");
            var refs = ctx.Local(ctx.Object, "refs");
            var needDefer = ctx.Local(ctx.Object, "needDefer");
            var defer = ctx.Local(ctx.Object, "defer");
            var dec = ctx.Local(ctx.Object, "dec");
            var type = ctx.Local(ctx.Type, "type");
            var ret = ctx.Local(ctx.Object, "ret");
            var o = ctx.Local(ctx.Object, "o");
            var oArray = ctx.Local(ctx.Object, "oArray");
            var i = ctx.Local(ctx.Int32, "i");
            var isObject = ctx.Local(ctx.Boolean, "isObject");
            var kVal = ctx.Local(ctx.Object, "kVal");
            var vVal = ctx.Local(ctx.Object, "vVal");
            var kRef = ctx.Local(ctx.Boolean, "kRef");
            var vRef = ctx.Local(ctx.Boolean, "vRef");
            var js = @"
objs = {};
refs = [];
needDefer = function(o) {
    return !!(o && o instanceof Array &&  o.length === 1 && typeof(o[0]) === 'string');
};
defer = function(ret, i, o) {
    if (needDefer(o[i])) {
        refs.push(function() {
            ret[i] = objs[o[i][0]];
        });
    } else {
        ret[i] = dec(o[i]);
    }
};
dec = function(o) {
    var ret, i;
    if (o == null) {
        return null;
    }
    var isObject = false;
    if (o._ !== undefined) {
        if (o.__ === 2) { // Dictionary
            ret = $d[o.d][0]({ _: $$[o._] });
            for (var i = 0; i < o.a.length; i++) {
                var kVal = o.a[i];
                var vVal = o.b[i];
                var kRef = needDefer(kVal);
                var vRef = needDefer(vVal);
                (function(kRef, kVal, vRef, vVal, o, ret) {
                    refs.push(function() {
                        if (kRef) kVal = objs[kVal[0]];
                        if (vRef) vVal = objs[vVal[0]];
                        $d[o.d][1](ret, kVal, vVal);
                    });
                })(kRef, kVal, vRef, vVal, o, ret);
            }
        } else if (o['']) { // Array
            var oArray = o[''];
            var ret = new Array(oArray.length);
            ret._ = $$[o._];
            // TODO: Set $
            for (var i = 0; i < oArray.length; i++) {
                defer(ret, i, oArray)
            }
        } else { // Object or boxed struct
            isObject = true;
        }
    } else if (typeof(o) === 'object' && !(o instanceof Array)) { // unboxed value-type
        isObject = true;
    } else if (o instanceof Array && o.length === 1) { // Special Single/Double
        switch (o[0]) {
        case 0: ret = NaN; break;
        case 1: ret = Number.POSITIVE_INFINITY; break;
        case -1: ret = Number.NEGATIVE_INFINITY; break;
        default: throw 'Unrecognised special: ' + o[0];
        }
    } else { // unboxed primitive or null
        ret = o;
    }
    if (isObject) {
        var ret = o._ ? { '_': $$[o._] } : { };
        // TODO: Set $ = hash id
        for (var i in o) {
            if (i !== '_') {
                defer(ret, i, o);
            }
        }
    }
    return ret;
};
for (i = 0; i < arg.length; i++) {
    objs[arg[i][0]] = dec(arg[i][1]);
}
for (i = 0; i < refs.length; i++) {
    refs[i]();
}
ret = objs['0'];
return ret;
";
            var stmt = new StmtJsExplicit(ctx, js, arg, objs, refs, needDefer, defer, dec, type, ret, o, oArray, i, isObject, kVal, vVal, kRef, vRef);
            return stmt;
        }
        public static Stmt FormatDouble(Ctx ctx) {
            var value = ctx.MethodParameter(0, "value");
            var format = ctx.MethodParameter(1, "format");
            var newFmtEx = new ExprNewObj(ctx, ctx.Module.Import(typeof(FormatException).GetConstructor(Type.EmptyTypes))).Named("newFmtEx");
            var valuePos = ctx.Local(ctx.Int32, "valuePos");
            var precision = ctx.Local(ctx.Int32.MakeNullable(), "precision");
            var fmt0 = ctx.Local(ctx.String, "fmt0");
            var s = ctx.Local(ctx.String, "s");
            var parts = ctx.Local(ctx.String.MakeArray(), "parts");
            var i = ctx.Local(ctx.Int32, "i");
            var js = @"
if (isNaN(value)) return 'NaN';
if (value === Number.POSITIVE_INFINITY) return 'Infinity';
if (value === Number.NEGATIVE_INFINITY) return '-Infinity';
format = format || 'G';
valuePos = Math.abs(value);
precision = format.length > 1 ? +format.substr(1) : null;
fmt0 = format.charAt(0);
switch (fmt0) {
case 'g':
case 'G':
    s = valuePos.toPrecision(precision || 15);
    if (s.indexOf('e') >= 0) {
        parts = s.split('e');
        parts[0] = parts[0].replace(/(\d)\.?0+$/, '$1');
        parts[1] = parts[1].replace(/^\+(\d)$/, '+0$1');
        s = parts.join(fmt0 === 'g' ? 'e' : 'E');
    } else if (s.indexOf('.') >= 0) {
        s = s.replace(/(\d)\.?0+$/g, '$1');
    }
    break;
case 'f':
case 'F':
case 'n':
case 'N':
    s = valuePos.toExponential(14);
    parts = s.replace('.', '').split('e');
    i = Number(parts[1]) + 1;
    s = parts[0];
    if (i <= 0) {
        s = '0' + Array(-i + 1).join('0') + s;
        i = 1;
    }
    if (precision === null) precision = 2;
    i += precision;
    if (s.length <= i) {
        s += Array(i - s.length + 1).join('0');
    } else {
        var needInc = (+s.charAt(i)) >= 5;
        s = s.substr(0, i);
        var cs = s.split('');
        if (needInc) {
            for (var j = cs.length - 1; j >= 0; j--) {
                if (++cs[j] < 10) {
                    needInc = false;
                    break;
                }
                cs[j] = 0;
            }
            if (needInc) {
                cs.unshift(1);
                i++;
            }
        }
        s = cs.join('');
    }
    i -= precision;
    if (fmt0 === 'n' || fmt0 === 'N') {
        s = s.substr(0, i).replace(/(\d)(?=(\d{3})+$)/g, '$1,') + (precision > 0 ? '.' + s.substr(i) : '');
    } else {
        s = s.substr(0, i) + (precision > 0 ? '.' + s.substr(i) : '');
    }
    break;
default:
    throw newFmtEx;
}
return value < 0 ? '-' + s : s;
";
            return new StmtJsExplicit(ctx, js, value, format, newFmtEx, valuePos, precision, fmt0, s, parts, i);
        }
            public Stmt GetImpl(Ctx ctx) {
                var a = ctx.MethodParameter(0, "a");
                var b = ctx.MethodParameter(1, "b");
                var u = ctx.Local(ctx.Int32.MakeArray(), "u");
                var v = ctx.Local(ctx.Int32.MakeArray(), "v");
                var m = ctx.Local(ctx.Int32, "m");
                var n = ctx.Local(ctx.Int32, "n");
                var r = ctx.Local(ctx.Int32.MakeArray(), "r");
                var q = ctx.Local(ctx.Int32.MakeArray(), "q");
                var i = ctx.Local(ctx.Int32, "i");
                var j = ctx.Local(ctx.Int32, "j");
                var k = ctx.Local(ctx.Int32, "k");
                var l = ctx.Local(ctx.Int32, "l");
                var p = ctx.Local(ctx.Int32, "p");
                var t = ctx.Local(ctx.Int32, "t");
                var s = ctx.Local(ctx.Int32, "s");
                var x = ctx.Local(ctx.Int32, "x");
                var qhat = ctx.Local(ctx.Int32, "qhat");
                var rhat = ctx.Local(ctx.Int32, "rhat");
                var mask = ctx.Literal(0xffff, ctx.Int32, "mask");
                var limit = ctx.Literal(0x10000, ctx.Int32, "limit");
                var divByZeroEx = new ExprNewObj(ctx, ctx.Module.Import(typeof(DivideByZeroException).GetConstructor(Type.EmptyTypes))).Named("divByZeroEx");
                var js = @"
v = [b[1] & mask, b[1] >>> 16, b[0] & mask, b[0] >>> 16];
while (v[v.length - 1] === 0) {
    v = v.slice(0, -1);
    if (v.length === 0) throw divByZeroEx;
}
n = v.length;
u = [a[1] & mask, a[1] >>> 16, a[0] & mask, a[0] >>> 16];
while (u[u.length - 1] === 0 && u.length > n) u = u.slice(0, -1);
m = u.length;
r = [0, 0, 0, 0];
q = [0, 0, 0, 0];
if (n === 1) {
    k = 0;
    for (j = m - 1; j >= 0; j--) {
        l = k * limit + u[j]
        q[j] = (l / v[0]) >>> 0;
        k = l - q[j] * v[0];
    }
    r[0] = k;
} else {
    x = v[n - 1];
    s = 16;
    while (x > 0) {
        x >>>= 1;
        s--;
    }
    l = 0;
    for (i = n - 1; i > 0; i--) v[i] = ((v[i] << s) | (v[i - 1] >> (16 - s))) & mask;
    v[0] = (v[0] << s) & mask;
    u.push(0);
    for (i = m; i> 0; i--) u[i] = ((u[i] << s) | (u[i - 1] >> (16 - s))) & mask;
    u[0] = (u[0] << s) & mask;
    for (j = m - n; j >= 0; j--) {
        l = u[j + n] * limit + u[j + n - 1];
        qhat = (l / v[n - 1]) >>> 0;
        rhat = l - qhat * v[n - 1];
        for (;;) {
            if (qhat >= limit || qhat * v[n - 2] > limit * rhat + u[j + n - 2]) {
                qhat--;
                rhat += v[n - 1];
                if (rhat < limit) continue;
            }
            break;
        }
        k = 0;
        for (i = 0; i < n; i++) {
            p = qhat * v[i];
            t = u[i + j] - k - (p & mask);
            u[i + j] = t & mask;
            k = (p >> 16) - (t >> 16);
        }
        t = u[j + n] - k;
        u[j + n] = t;
        q[j] = qhat;
        if (t < 0) {
            q[j]--;
            k = 0;
            for (i = 0; i < n; i++) {
                t = u[i + j] + n[i] + k;
                u[i + j] = t & mask;
                k = t >> 16;
            }
            u[j + n] += k;
        }
    }
    for (i = 0; i< n; i++) {
        r[i] = ((u[i] >> s) | (u[i + 1] << (16 - s))) & mask;
    }
}
return [[q[2] + q[3] * limit, q[0] + q[1] * limit], [r[2] + r[3] * limit, r[0] + r[1] * limit]];
";
                var stmt = new StmtJsExplicit(ctx, js, a, b, u, v, m, n, r, q, i, j, k, l, p, s, t, qhat, rhat, mask, limit, divByZeroEx);
                return stmt;
            }
 private static Stmt FindStmtReturn(Ctx ctx) {
     var mRef = ctx.MRef;
     var mRefRedirected = GetRedirect(mRef);
     if (mRefRedirected != null) {
         mRef = mRefRedirected;
     }
     var mDef = mRef.Resolve();
     var jsAttr = mDef.GetCustomAttribute<JsAttribute>();
     if (jsAttr != null) {
         var ctorArgs = jsAttr.ConstructorArguments;
         if (ctorArgs.Count == 2) {
             if (ctorArgs[0].Type.IsType() && ((Array)ctorArgs[1].Value).Length == 0) {
                 // IJsImpl class provides the implementation
                 var iJsImpltype = ((TypeReference)ctorArgs[0].Value).LoadType();
                 var iJsImpl = (IJsImpl)Activator.CreateInstance(iJsImpltype);
                 var stmt = iJsImpl.GetImpl(ctx);
                 return stmt;
             }
         } else if (ctorArgs.Count == 1) {
             if (ctorArgs[0].Type.IsString()) {
                 // Explicit JS string provides implementation
                 var js = (string)ctorArgs[0].Value;
                 var parameters = mRef.Parameters.Select((x, i) => ctx.MethodParameter(i, ((char)('a' + i)).ToString())).ToArray();
                 var stmt = new StmtJsExplicit(ctx, js, parameters.Concat(ctx.ThisNamed));
                 return stmt;
             }
         }
     }
     var mappedType = TypeMap(ctx.TRef);
     if (mappedType == null && mDef.GetCustomAttribute<JsRedirectAttribute>() != null) {
         mappedType = ctx.TRef;
     }
     if (mappedType != null) {
         var mappedMRef = FindJsMember(mRef, mappedType);
         if (mappedMRef != null) {
             if (mappedMRef.ReturnType.FullName == typeof(Stmt).FullName) {
                 var m = mappedMRef.LoadMethod();
                 var stmt = (Stmt)m.Invoke(null, new object[] { ctx });
                 return stmt;
             }
         }
     }
     return null;
 }
 public static Stmt Equals(Ctx ctx) {
     var other = ctx.MethodParameter(0).Named("other");
     var stmt = new StmtJsExplicit(ctx, "return this===other;", ctx.ThisNamed, other);
     return stmt;
 }
Exemple #14
0
 public static Stmt Cos(Ctx ctx) {
     var arg = ctx.MethodParameter(0);
     var eg = ctx.ExprGen;
     return new StmtReturn(ctx,
         new ExprTernary(ctx,
             new ExprJsResolvedMethod(ctx, ctx.Boolean, null, "Number.isFinite", arg),
             new ExprTernary(ctx,
                 eg.And(
                     eg.GreaterThan(arg, new ExprJsExplicit(ctx, long.MinValue.ToString(), ctx.Int64)),
                     eg.LessThan(arg, new ExprJsExplicit(ctx, long.MaxValue.ToString(), ctx.Int64))
                 ),
                 new ExprJsResolvedMethod(ctx, ctx.Double, null, "Math.cos", arg),
                 arg
             ),
             ctx.Literal(Double.NaN)
         )
     );
 }
Exemple #15
0
 public static Stmt Ceiling(Ctx ctx) {
     var arg = ctx.MethodParameter(0);
     var e = new ExprTernary(ctx,
         new ExprJsResolvedMethod(ctx, ctx.Boolean, null, "Number.isFinite", arg),
         new ExprJsResolvedMethod(ctx, ctx.Double, null, "Math.ceil", arg),
         arg);
     return new StmtReturn(ctx, e);
 }
        public static Stmt FormatInt32(Ctx ctx) {
            var value = ctx.MethodParameter(0, "value");
            var format = ctx.MethodParameter(1, "format");
            var newFmtEx = new ExprNewObj(ctx, ctx.Module.Import(typeof(FormatException).GetConstructor(Type.EmptyTypes))).Named("newFmtEx");
            var valuePos = ctx.Local(ctx.Int32, "valuePos");
            var precision = ctx.Local(ctx.Int32.MakeNullable(), "precision");
            var fmt0 = ctx.Local(ctx.String, "fmt0");
            var s = ctx.Local(ctx.String, "s");
            var parts = ctx.Local(ctx.String.MakeArray(), "parts");
            var js = @"
format = format || 'G';
valuePos = Math.abs(value);
precision = format.length > 1 ? +format.substr(1) : null;
fmt0 = format.charAt(0);
switch (fmt0) {
case 'd':
case 'D':
    s = valuePos.toString();
    if (precision !== null && precision > s.length) {
        s = Array(precision - s.length + 1).join('0') + s;
    }
    break;
case 'g':
case 'G':
    s = valuePos.toString();
    if (precision !== null && precision < s.length && precision > 0) {
        s = valuePos.toPrecision(precision);
        parts = s.split('e');
        parts[0] = parts[0].replace(/(\d)\.?0+$/, '$1');
        parts[1] = parts[1].replace(/^\+(\d)$/, '+0$1');
        s = parts.join(fmt0 === 'g' ? 'e' : 'E');
    }
    break;
case 'n':
case 'N':
    if (precision === null) precision = 2;
    s = valuePos.toFixed(precision);
    parts = s.split('.');
    parts[0] = parts[0].replace(/(\d)(?=(\d{3})+$)/g, '$1,');
    s = parts.join('.');
    break;
case 'x':
case 'X':
    if (value < 0) {
        value += 0x100000000;
    }
    s = value.toString(16);
    if (fmt0 === 'X') {
        s = s.toUpperCase();
    }
    if (precision !== null && precision > s.length) {
        s = Array(precision - s.length + 1).join('0') + s;
    }
    break;
default:
    throw newFmtEx;
}
return value < 0 ? '-' + s : s;
";
            return new StmtJsExplicit(ctx, js, value, format, newFmtEx, valuePos, precision, fmt0, s, parts);
        }
 public Stmt GetImpl(Ctx ctx) {
     var a = ctx.MethodParameter(0, "a");
     var stmt = new StmtJsExplicit(ctx, "return [(~a[0]) >>> 0, (~a[1]) >>> 0];", a);
     return stmt;
 }
        public static Stmt FormatInt64(Ctx ctx) {
                        var value = ctx.MethodParameter(0, "value");
            var format = ctx.MethodParameter(1, "format");
            var neg = ctx.Local(ctx.Boolean, "neg");
            var precision = ctx.Local(ctx.Int32.MakeNullable(), "precision");
            var fmt0 = ctx.Local(ctx.String, "fmt0");
            var i = ctx.Local(ctx.Int32, "i");
            var s = ctx.Local(ctx.String, "s");
            var ss = ctx.Local(ctx.String, "ss");
            var c = ctx.Local(ctx.String, "c");
            var inc = ctx.Local(ctx.Boolean, "inc");
            var divMod10 = ctx.Local(ctx.Int64.MakeArray(), "divMod10");
            var valueDivMod10 = new ExprCall(ctx, (Func<UInt64, UInt64, object>)_Int64UInt64.UInt64DivRem, null, value.Expr, ctx.Literal(10L)).Named("valueDivMod10");
            var valueNeg = new ExprCall(ctx, (Func<Int64, Int64, Int64>)_Int64.Subtract, null, ctx.Literal(0L), value.Expr).Named("valueNeg");
            var sLen = ctx.Local(ctx.Int32, "sLen");
            var newFmtEx = new ExprNewObj(ctx, ctx.Module.Import(typeof(FormatException).GetConstructor(Type.EmptyTypes))).Named("newFmtEx");
            var js = @"
format = format || 'G';
precision = format.length > 1 ? +format.substr(1) : null;
fmt0 = format.charAt(0);
if (fmt0 === 'x' || fmt0 === 'X') {
    s = value[1].toString(16);
    if (value[0] !== 0) {
        s = value[0].toString(16) + Array(9 - s.length).join('0') + s;
    }
    if (fmt0 === 'X') {
        s = s.toUpperCase();
    }
    if (precision !== null && precision > s.length) {
        s = Array(precision - s.length + 1).join('0') + s;
    }
    return s;
}
if (value[0] === 0 && value[1] === 0) {
    s = '0';
} else if (value[0] === 0x80000000 && value[1] === 0) {
    s = '9223372036854775808';
    neg = true;
} else {
    if (value[0] >= 0x80000000) {
        value = valueNeg;
        neg = true;
    }
    s = '';
    while (value[0] !== 0 || value[1] !== 0) {
        divMod10 = valueDivMod10;
        value = divMod10[0];
        s = String.fromCharCode(48 + divMod10[1][1]) + s;
    }
}
switch (fmt0) {
case 'g':
case 'G':
    if (precision !== null && precision < s.length && precision > 0) {
        sLen = s.length;
        inc = +(s.charAt(precision)) >= 5;
        s = s.substr(0, precision);
        ss = '';
        for (i = precision - 1; i >= 0; i--) {
            c = s.charAt(i);
            if (inc) {
                c = (+c) + 1;
                if (c > 9) {
                    c = 0;
                } else {
                    inc = false;
                }
                ss = String.fromCharCode(48 + c) + ss;
            } else {
                ss = c + ss;
            }
        }
        if (inc) {
            sLen++;
            ss = '1' + ss.substr(0, ss.length - 1);
        }
        if (ss.length > 1) {
            ss = ss.charAt(0) + '.' + ss.substr(1);
        }
        s = ss.replace(/(\d)\.?0+$/, '$1');
        s += (fmt0 === 'g' ? 'e' : 'E') + '+' + (sLen - 1).toFixed().replace(/^(\d)$/, '0$1');;
    }
    break;
case 'd':
case 'D':
    if (precision !== null && precision > s.length) {
        s = Array(precision - s.length + 1).join('0') + s;
    }
    break;
case 'n':
case 'N':
    if (precision === null) precision = 2;
    s = s.replace(/(\d)(?=(\d{3})+$)/g, '$1,');
    if (precision > 0) {
        s += '.' + Array(precision + 1).join('0');
    }
    break;
default:
    throw newFmtEx;
}
return neg ? '-' + s : s;
";
            return new StmtJsExplicit(ctx, js, value, format, neg, precision, fmt0, i, s, ss, c, inc, divMod10, valueDivMod10, valueNeg, sLen, newFmtEx);
        }
 public Stmt GetImpl(Ctx ctx) {
     var a = ctx.MethodParameter(0, "a");
     var b = ctx.MethodParameter(1, "b");
     var stmt = new StmtJsExplicit(ctx, "return [(a[0] ^ b[0]) >>> 0, (a[1] ^ b[1]) >>> 0];", a, b);
     return stmt;
 }
        public static Stmt Encode(Ctx ctx) {
            var arg = ctx.MethodParameter(0, "arg");
            var id = ctx.Local(ctx.Int32, "id");
            var todo = ctx.Local(ctx.Object, "todo");
            var todoOfs = ctx.Local(ctx.Int32, "todoOfs");
            var enc = ctx.Local(ctx.Object, "enc");
            var obj = ctx.Local(ctx.Object, "obj");
            var json = ctx.Local(ctx.Object, "json");
            var jsonPart = ctx.Local(ctx.Object, "jsonPart");
            var o = ctx.Local(ctx.Object, "o");
            var type = ctx.Local(ctx.Type, "type");
            var oKey = ctx.Local(ctx.String, "oKey");
            var isRoot = ctx.Local(ctx.Boolean, "isRoot");
            var i = ctx.Local(ctx.Int32, "i");
            var isArray = new ExprJsTypeData(ctx, TypeData.IsArray).Named("isArray");
            var jsName = new ExprJsTypeData(ctx, TypeData.JsName).Named("jsName");
            var jsIsDict = new ExprJsTypeData(ctx, TypeData.IsDictionary).Named("jsIsDict");
            var slots = ctx.Local(ctx.Object, "slots");
            var ret = ctx.Local(ctx.Object, "ret");
            // Value-types will be boxed on entry
            var js = @"
try {
id = 0;
if (arg && arg._) {
    arg.$$ = '0';
}
todo = [arg];
todoOfs = 0;
enc = function(o, isRoot) {
    if (o === null || o === undefined) {
        return null;
    }
    var type = o._;
    if (!type) { // Unboxed value-type/primitive
        if (typeof(o) !== 'object' || o instanceof Array) { // primitive number, boolean, string, 64-bit number (array)
            if (typeof(o) === 'number') { // Number
                if (isNaN(o)) {
                    return [0];
                }
                if (o === Number.NEGATIVE_INFINITY) {
                    return [-1];
                }
                if (o === Number.POSITIVE_INFINITY) {
                    return [1];
                }
            }
            return o;
        } else {
            // Non-primitive value-type
            var ret = {};
            for (var oKey in o) {
                ret[oKey] = enc(o[oKey]);
            }
            return ret;
        }
    }
    if (isRoot) {
        // Direct object encoding required
        if (type.jsIsDict) {
            var ret = { '_': type.jsName, 'v': [] };
            var slots = o[type.jsIsDict[0]];
            for (var i=0; i<slots.length; i++) {
                if (slots[i] && slots[i][type.jsIsDict[1]] >= 0) {
                    ret.v.push(enc(slots[i][type.jsIsDict[2]]), enc(slots[i][type.jsIsDict[3]]));
                }
            }
            return ret;
        }
        if (type && type.isArray) {
            var ret = { '_': type.jsName, 'v': [] };
            for (var i=0; i<o.length; i++) {
                ret.v.push(enc(o[i]));
            }
            return ret;
        } else {
            var ret = { '_': type.jsName };
            for (var oKey in o) {
                if (oKey.charAt(0) !== '_' && oKey.charAt(0) !== '$') {
                    ret[oKey] = enc(o[oKey]);
                }
            }
            return ret;
        }
    } else {
        if (!o.$$) {
            o.$$ = (++id).toString();
            todo.push(o);
        }
        return [o.$$];
    }
};
json = [];
while (todo.length > todoOfs) {
    obj = todo[todoOfs++];
    jsonPart = enc(obj, true);
    json.push([(obj && obj.$$) || '0', jsonPart]);
}
for (i = 0; i<todo.length; i++) {
    if (todo[i] && todo[i].$$) {
        delete todo[i].$$;
    }
}
return json;
} catch (eeee) {
console.log('Ex: ' + eeee);
throw eeee;
}
";
            var stmt = new StmtJsExplicit(ctx, js, arg, id, todo, todoOfs, enc, obj, json, jsonPart, o, type, oKey, isRoot, i, isArray, ret, jsName, jsIsDict, slots);
            return stmt;
        }
 public Stmt GetImpl(Ctx ctx) {
     var a = ctx.MethodParameter(0, "a");
     var b = ctx.MethodParameter(1, "b");
     var stmt = new StmtJsExplicit(ctx, "return a[0] !== b[0] || a[1] !== b[1];", a, b);
     return stmt;
 }
 public static Stmt Equals(Ctx ctx) {
     var other = ctx.MethodParameter(0).Named("other");
     var type = new ExprJsTypeVarName(ctx, ctx.Single).Named("type");
     return new StmtJsExplicit(ctx, "return other._ === type && this === other.v;", ctx.ThisNamed, other, type);
 }
            public Stmt GetImpl(Ctx ctx) {
                var a = ctx.MethodParameter(0, "a");
                var b = ctx.MethodParameter(1, "b");
                var neg = ctx.Local(ctx.Boolean, "neg");
                var aNegate = new ExprUnary(ctx, UnaryOp.Negate, ctx.Int64, a.Expr).Named("aNegate");
                var bNegate = new ExprUnary(ctx, UnaryOp.Negate, ctx.Int64, b.Expr).Named("bNegate");
                var divMod = new ExprCall(ctx, (Func<UInt64, UInt64, object>)_Int64UInt64.UInt64DivRem, null, a.Expr, b.Expr).Named("divMod");
                var r = ctx.Local(ctx.Int64, "r");
                var rNegate = new ExprUnary(ctx, UnaryOp.Negate, ctx.Int64, r.Expr).Named("rNegate");
                // TODO: Throw ArithmeticException if a == Int64.MinValue and b == -1
                // TODO: Handle a or b being Int64.MinValue
                var js = @"
neg = false;
if (a[0] >>> 31) {
    a = aNegate;
    neg = true;
}
if (b[0] >>> 31) b = bNegate;
r = divMod[1];
return neg ? rNegate : r;
";
                var stmt = new StmtJsExplicit(ctx, js, a, b, neg, r, aNegate, bNegate, divMod, rNegate);
                return stmt;
            }