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 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 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 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 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 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 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; }
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; }