Created
April 27, 2015 04:24
-
-
Save andyfriesen/b1c5519f577bcacf2619 to your computer and use it in GitHub Desktop.
Hello World, as produced by Haste
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This object will hold all exports. | |
var Haste = {}; | |
/* Thunk | |
Creates a thunk representing the given closure. | |
If the non-updatable flag is undefined, the thunk is updatable. | |
*/ | |
function T(f, nu) { | |
this.f = f; | |
if(nu === undefined) { | |
this.x = __updatable; | |
} | |
} | |
function F(f) { | |
this.f = f; | |
} | |
// Special object used for blackholing. | |
var __blackhole = {}; | |
// Used to indicate that an object is updatable. | |
var __updatable = {}; | |
/* Apply | |
Applies the function f to the arguments args. If the application is under- | |
saturated, a closure is returned, awaiting further arguments. If it is over- | |
saturated, the function is fully applied, and the result (assumed to be a | |
function) is then applied to the remaining arguments. | |
*/ | |
function A(f, args) { | |
if(f instanceof T) { | |
f = E(f); | |
} | |
// Closure does some funny stuff with functions that occasionally | |
// results in non-functions getting applied, so we have to deal with | |
// it. | |
if(!(f instanceof Function)) { | |
f = B(f); | |
if(!(f instanceof Function)) { | |
return f; | |
} | |
} | |
if(f.arity === undefined) { | |
f.arity = f.length; | |
} | |
if(args.length === f.arity) { | |
switch(f.arity) { | |
case 0: return f(); | |
case 1: return f(args[0]); | |
default: return f.apply(null, args); | |
} | |
} else if(args.length > f.arity) { | |
switch(f.arity) { | |
case 0: return f(); | |
case 1: return A(f(args.shift()), args); | |
default: return A(f.apply(null, args.splice(0, f.arity)), args); | |
} | |
} else { | |
var g = function() { | |
return A(f, args.concat(Array.prototype.slice.call(arguments))); | |
}; | |
g.arity = f.arity - args.length; | |
return g; | |
} | |
} | |
/* Eval | |
Evaluate the given thunk t into head normal form. | |
If the "thunk" we get isn't actually a thunk, just return it. | |
*/ | |
function E(t) { | |
if(t instanceof T) { | |
if(t.f !== __blackhole) { | |
var f = t.f; | |
t.f = __blackhole; | |
if(t.x === __updatable) { | |
t.x = f(); | |
} else { | |
return f(); | |
} | |
} | |
return t.x; | |
} else { | |
return t; | |
} | |
} | |
/* Bounce | |
Bounce on a trampoline for as long as we get a function back. | |
*/ | |
function B(f) { | |
while(f instanceof F) { | |
var fun = f.f; | |
f.f = __blackhole; | |
f = fun(); | |
} | |
return f; | |
} | |
// Export Haste, A, B and E. Haste because we need to preserve exports, A, B | |
// and E because they're handy for Haste.Foreign. | |
if(!window) { | |
var window = {}; | |
} | |
window['Haste'] = Haste; | |
window['A'] = A; | |
window['E'] = E; | |
window['B'] = B; | |
/* Throw an error. | |
We need to be able to use throw as an exception so we wrap it in a function. | |
*/ | |
function die(err) { | |
throw err; | |
} | |
function quot(a, b) { | |
return (a-a%b)/b; | |
} | |
function quotRemI(a, b) { | |
return [0, (a-a%b)/b, a%b]; | |
} | |
// 32 bit integer multiplication, with correct overflow behavior | |
// note that |0 or >>>0 needs to be applied to the result, for int and word | |
// respectively. | |
if(Math.imul) { | |
var imul = Math.imul; | |
} else { | |
var imul = function(a, b) { | |
// ignore high a * high a as the result will always be truncated | |
var lows = (a & 0xffff) * (b & 0xffff); // low a * low b | |
var aB = (a & 0xffff) * (b & 0xffff0000); // low a * high b | |
var bA = (a & 0xffff0000) * (b & 0xffff); // low b * high a | |
return lows + aB + bA; // sum will not exceed 52 bits, so it's safe | |
} | |
} | |
function addC(a, b) { | |
var x = a+b; | |
return [0, x & 0xffffffff, x > 0x7fffffff]; | |
} | |
function subC(a, b) { | |
var x = a-b; | |
return [0, x & 0xffffffff, x < -2147483648]; | |
} | |
function sinh (arg) { | |
return (Math.exp(arg) - Math.exp(-arg)) / 2; | |
} | |
function tanh (arg) { | |
return (Math.exp(arg) - Math.exp(-arg)) / (Math.exp(arg) + Math.exp(-arg)); | |
} | |
function cosh (arg) { | |
return (Math.exp(arg) + Math.exp(-arg)) / 2; | |
} | |
// Scratch space for byte arrays. | |
var rts_scratchBuf = new ArrayBuffer(8); | |
var rts_scratchW32 = new Uint32Array(rts_scratchBuf); | |
var rts_scratchFloat = new Float32Array(rts_scratchBuf); | |
var rts_scratchDouble = new Float64Array(rts_scratchBuf); | |
function decodeFloat(x) { | |
rts_scratchFloat[0] = x; | |
var sign = x < 0 ? -1 : 1; | |
var exp = ((rts_scratchW32[0] >> 23) & 0xff) - 150; | |
var man = rts_scratchW32[0] & 0x7fffff; | |
if(exp === 0) { | |
++exp; | |
} else { | |
man |= (1 << 23); | |
} | |
return [0, sign*man, exp]; | |
} | |
function decodeDouble(x) { | |
rts_scratchDouble[0] = x; | |
var sign = x < 0 ? -1 : 1; | |
var manHigh = rts_scratchW32[1] & 0xfffff; | |
var manLow = rts_scratchW32[0]; | |
var exp = ((rts_scratchW32[1] >> 20) & 0x7ff) - 1075; | |
if(exp === 0) { | |
++exp; | |
} else { | |
manHigh |= (1 << 20); | |
} | |
return [0, sign, manHigh, manLow, exp]; | |
} | |
function isFloatFinite(x) { | |
return isFinite(x); | |
} | |
function isDoubleFinite(x) { | |
return isFinite(x); | |
} | |
function err(str) { | |
die(toJSStr(str)); | |
} | |
/* unpackCString# | |
NOTE: update constructor tags if the code generator starts munging them. | |
*/ | |
function unCStr(str) {return unAppCStr(str, [0]);} | |
function unFoldrCStr(str, f, z) { | |
var acc = z; | |
for(var i = str.length-1; i >= 0; --i) { | |
acc = B(A(f, [[0, str.charCodeAt(i)], acc])); | |
} | |
return acc; | |
} | |
function unAppCStr(str, chrs) { | |
var i = arguments[2] ? arguments[2] : 0; | |
if(i >= str.length) { | |
return E(chrs); | |
} else { | |
return [1,[0,str.charCodeAt(i)],new T(function() { | |
return unAppCStr(str,chrs,i+1); | |
})]; | |
} | |
} | |
function charCodeAt(str, i) {return str.charCodeAt(i);} | |
function fromJSStr(str) { | |
return unCStr(E(str)); | |
} | |
function toJSStr(hsstr) { | |
var s = ''; | |
for(var str = E(hsstr); str[0] == 1; str = E(str[2])) { | |
s += String.fromCharCode(E(str[1])[1]); | |
} | |
return s; | |
} | |
// newMutVar | |
function nMV(val) { | |
return ({x: val}); | |
} | |
// readMutVar | |
function rMV(mv) { | |
return mv.x; | |
} | |
// writeMutVar | |
function wMV(mv, val) { | |
mv.x = val; | |
} | |
// atomicModifyMutVar | |
function mMV(mv, f) { | |
var x = B(A(f, [mv.x])); | |
mv.x = x[1]; | |
return x[2]; | |
} | |
function localeEncoding() { | |
var le = newByteArr(5); | |
le['v']['i8'][0] = 'U'.charCodeAt(0); | |
le['v']['i8'][1] = 'T'.charCodeAt(0); | |
le['v']['i8'][2] = 'F'.charCodeAt(0); | |
le['v']['i8'][3] = '-'.charCodeAt(0); | |
le['v']['i8'][4] = '8'.charCodeAt(0); | |
return le; | |
} | |
var isDoubleNaN = isNaN; | |
var isFloatNaN = isNaN; | |
function isDoubleInfinite(d) { | |
return (d === Infinity); | |
} | |
var isFloatInfinite = isDoubleInfinite; | |
function isDoubleNegativeZero(x) { | |
return (x===0 && (1/x)===-Infinity); | |
} | |
var isFloatNegativeZero = isDoubleNegativeZero; | |
function strEq(a, b) { | |
return a == b; | |
} | |
function strOrd(a, b) { | |
if(a < b) { | |
return [0]; | |
} else if(a == b) { | |
return [1]; | |
} | |
return [2]; | |
} | |
function jsCatch(act, handler) { | |
try { | |
return B(A(act,[0])); | |
} catch(e) { | |
return B(A(handler,[e, 0])); | |
} | |
} | |
/* Haste represents constructors internally using 1 for the first constructor, | |
2 for the second, etc. | |
However, dataToTag should use 0, 1, 2, etc. Also, booleans might be unboxed. | |
*/ | |
function dataToTag(x) { | |
if(x instanceof Array) { | |
return x[0]; | |
} else { | |
return x; | |
} | |
} | |
function __word_encodeDouble(d, e) { | |
return d * Math.pow(2,e); | |
} | |
var __word_encodeFloat = __word_encodeDouble; | |
var jsRound = Math.round; | |
var jsTrunc = Math.trunc ? Math.trunc : function(x) { | |
return x < 0 ? Math.ceil(x) : Math.floor(x); | |
}; | |
function jsRoundW(n) { | |
return Math.abs(jsTrunc(n)); | |
} | |
var realWorld = undefined; | |
if(typeof _ == 'undefined') { | |
var _ = undefined; | |
} | |
function popCnt(i) { | |
i = i - ((i >> 1) & 0x55555555); | |
i = (i & 0x33333333) + ((i >> 2) & 0x33333333); | |
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; | |
} | |
function jsAlert(val) { | |
if(typeof alert != 'undefined') { | |
alert(val); | |
} else { | |
print(val); | |
} | |
} | |
function jsLog(val) { | |
console.log(val); | |
} | |
function jsPrompt(str) { | |
var val; | |
if(typeof prompt != 'undefined') { | |
val = prompt(str); | |
} else { | |
print(str); | |
val = readline(); | |
} | |
return val == undefined ? '' : val.toString(); | |
} | |
function jsEval(str) { | |
var x = eval(str); | |
return x == undefined ? '' : x.toString(); | |
} | |
function isNull(obj) { | |
return obj === null; | |
} | |
function jsRead(str) { | |
return Number(str); | |
} | |
function jsShowI(val) {return val.toString();} | |
function jsShow(val) { | |
var ret = val.toString(); | |
return val == Math.round(val) ? ret + '.0' : ret; | |
} | |
function jsGetMouseCoords(e) { | |
var posx = 0; | |
var posy = 0; | |
if (!e) var e = window.event; | |
if (e.pageX || e.pageY) { | |
posx = e.pageX; | |
posy = e.pageY; | |
} | |
else if (e.clientX || e.clientY) { | |
posx = e.clientX + document.body.scrollLeft | |
+ document.documentElement.scrollLeft; | |
posy = e.clientY + document.body.scrollTop | |
+ document.documentElement.scrollTop; | |
} | |
return [posx - (e.currentTarget.offsetLeft || 0), | |
posy - (e.currentTarget.offsetTop || 0)]; | |
} | |
function jsSetCB(elem, evt, cb) { | |
// Count return press in single line text box as a change event. | |
if(evt == 'change' && elem.type.toLowerCase() == 'text') { | |
setCB(elem, 'keyup', function(k) { | |
if(k == '\n'.charCodeAt(0)) { | |
B(A(cb,[[0,k.keyCode],0])); | |
} | |
}); | |
} | |
var fun; | |
switch(evt) { | |
case 'click': | |
case 'dblclick': | |
case 'mouseup': | |
case 'mousedown': | |
fun = function(x) { | |
var mpos = jsGetMouseCoords(x); | |
var mx = [0,mpos[0]]; | |
var my = [0,mpos[1]]; | |
B(A(cb,[[0,x.button],[0,mx,my],0])); | |
}; | |
break; | |
case 'mousemove': | |
case 'mouseover': | |
fun = function(x) { | |
var mpos = jsGetMouseCoords(x); | |
var mx = [0,mpos[0]]; | |
var my = [0,mpos[1]]; | |
B(A(cb,[[0,mx,my],0])); | |
}; | |
break; | |
case 'keypress': | |
case 'keyup': | |
case 'keydown': | |
fun = function(x) {B(A(cb,[[0,x.keyCode],0]));}; | |
break; | |
case 'wheel': | |
fun = function(x) { | |
var mpos = jsGetMouseCoords(x); | |
var mx = [0,mpos[0]]; | |
var my = [0,mpos[1]]; | |
var mdx = [0,x.deltaX]; | |
var mdy = [0,x.deltaY]; | |
var mdz = [0,x.deltaZ]; | |
B(A(cb,[[0,mx,my],[0,mdx,mdy,mdz],0])); | |
}; | |
break; | |
default: | |
fun = function() {B(A(cb,[0]));}; | |
break; | |
} | |
return setCB(elem, evt, fun); | |
} | |
function setCB(elem, evt, cb) { | |
if(elem.addEventListener) { | |
elem.addEventListener(evt, cb, false); | |
return true; | |
} else if(elem.attachEvent) { | |
elem.attachEvent('on'+evt, cb); | |
return true; | |
} | |
return false; | |
} | |
function jsSetTimeout(msecs, cb) { | |
window.setTimeout(function() {B(A(cb,[0]));}, msecs); | |
} | |
function jsGet(elem, prop) { | |
return elem[prop].toString(); | |
} | |
function jsSet(elem, prop, val) { | |
elem[prop] = val; | |
} | |
function jsGetAttr(elem, prop) { | |
if(elem.hasAttribute(prop)) { | |
return elem.getAttribute(prop).toString(); | |
} else { | |
return ""; | |
} | |
} | |
function jsSetAttr(elem, prop, val) { | |
elem.setAttribute(prop, val); | |
} | |
function jsGetStyle(elem, prop) { | |
return elem.style[prop].toString(); | |
} | |
function jsSetStyle(elem, prop, val) { | |
elem.style[prop] = val; | |
} | |
function jsKillChild(child, parent) { | |
parent.removeChild(child); | |
} | |
function jsClearChildren(elem) { | |
while(elem.hasChildNodes()){ | |
elem.removeChild(elem.lastChild); | |
} | |
} | |
function jsFind(elem) { | |
var e = document.getElementById(elem) | |
if(e) { | |
return [1,[0,e]]; | |
} | |
return [0]; | |
} | |
function jsElemsByClassName(cls) { | |
var es = document.getElementsByClassName(cls); | |
var els = [0]; | |
for (var i = es.length-1; i >= 0; --i) { | |
els = [1, [0, es[i]], els]; | |
} | |
return els; | |
} | |
function jsQuerySelectorAll(elem, query) { | |
var els = [0], nl; | |
if (!elem || typeof elem.querySelectorAll !== 'function') { | |
return els; | |
} | |
nl = elem.querySelectorAll(query); | |
for (var i = nl.length-1; i >= 0; --i) { | |
els = [1, [0, nl[i]], els]; | |
} | |
return els; | |
} | |
function jsCreateElem(tag) { | |
return document.createElement(tag); | |
} | |
function jsCreateTextNode(str) { | |
return document.createTextNode(str); | |
} | |
function jsGetChildBefore(elem) { | |
elem = elem.previousSibling; | |
while(elem) { | |
if(typeof elem.tagName != 'undefined') { | |
return [1,[0,elem]]; | |
} | |
elem = elem.previousSibling; | |
} | |
return [0]; | |
} | |
function jsGetLastChild(elem) { | |
var len = elem.childNodes.length; | |
for(var i = len-1; i >= 0; --i) { | |
if(typeof elem.childNodes[i].tagName != 'undefined') { | |
return [1,[0,elem.childNodes[i]]]; | |
} | |
} | |
return [0]; | |
} | |
function jsGetFirstChild(elem) { | |
var len = elem.childNodes.length; | |
for(var i = 0; i < len; i++) { | |
if(typeof elem.childNodes[i].tagName != 'undefined') { | |
return [1,[0,elem.childNodes[i]]]; | |
} | |
} | |
return [0]; | |
} | |
function jsGetChildren(elem) { | |
var children = [0]; | |
var len = elem.childNodes.length; | |
for(var i = len-1; i >= 0; --i) { | |
if(typeof elem.childNodes[i].tagName != 'undefined') { | |
children = [1, [0,elem.childNodes[i]], children]; | |
} | |
} | |
return children; | |
} | |
function jsSetChildren(elem, children) { | |
children = E(children); | |
jsClearChildren(elem, 0); | |
while(children[0] === 1) { | |
elem.appendChild(E(E(children[1])[1])); | |
children = E(children[2]); | |
} | |
} | |
function jsAppendChild(child, container) { | |
container.appendChild(child); | |
} | |
function jsAddChildBefore(child, container, after) { | |
container.insertBefore(child, after); | |
} | |
var jsRand = Math.random; | |
// Concatenate a Haskell list of JS strings | |
function jsCat(strs, sep) { | |
var arr = []; | |
strs = E(strs); | |
while(strs[0]) { | |
strs = E(strs); | |
arr.push(E(strs[1])[1]); | |
strs = E(strs[2]); | |
} | |
return arr.join(sep); | |
} | |
var jsJSONParse = JSON.parse; | |
// JSON stringify a string | |
function jsStringify(str) { | |
return JSON.stringify(str); | |
} | |
// Parse a JSON message into a Haste.JSON.JSON value. | |
// As this pokes around inside Haskell values, it'll need to be updated if: | |
// * Haste.JSON.JSON changes; | |
// * E() starts to choke on non-thunks; | |
// * data constructor code generation changes; or | |
// * Just and Nothing change tags. | |
function jsParseJSON(str) { | |
try { | |
var js = JSON.parse(str); | |
var hs = toHS(js); | |
} catch(_) { | |
return [0]; | |
} | |
return [1,hs]; | |
} | |
function toHS(obj) { | |
switch(typeof obj) { | |
case 'number': | |
return [0, jsRead(obj)]; | |
case 'string': | |
return [1, obj]; | |
case 'boolean': | |
return [2, obj]; // Booleans are special wrt constructor tags! | |
case 'object': | |
if(obj instanceof Array) { | |
return [3, arr2lst_json(obj, 0)]; | |
} else if (obj == null) { | |
return [5]; | |
} else { | |
// Object type but not array - it's a dictionary. | |
// The RFC doesn't say anything about the ordering of keys, but | |
// considering that lots of people rely on keys being "in order" as | |
// defined by "the same way someone put them in at the other end," | |
// it's probably a good idea to put some cycles into meeting their | |
// misguided expectations. | |
var ks = []; | |
for(var k in obj) { | |
ks.unshift(k); | |
} | |
var xs = [0]; | |
for(var i = 0; i < ks.length; i++) { | |
xs = [1, [0, [0,ks[i]], toHS(obj[ks[i]])], xs]; | |
} | |
return [4, xs]; | |
} | |
} | |
} | |
function arr2lst_json(arr, elem) { | |
if(elem >= arr.length) { | |
return [0]; | |
} | |
return [1, toHS(arr[elem]), new T(function() {return arr2lst_json(arr,elem+1);}),true] | |
} | |
function arr2lst(arr, elem) { | |
if(elem >= arr.length) { | |
return [0]; | |
} | |
return [1, arr[elem], new T(function() {return arr2lst(arr,elem+1);})] | |
} | |
window['arr2lst'] = arr2lst; | |
function lst2arr(xs) { | |
var arr = []; | |
for(; xs[0]; xs = E(xs[2])) { | |
arr.push(E(xs[1])); | |
} | |
return arr; | |
} | |
window['lst2arr'] = lst2arr; | |
function ajaxReq(method, url, async, postdata, cb) { | |
var xhr = new XMLHttpRequest(); | |
xhr.open(method, url, async); | |
if(method == "POST") { | |
xhr.setRequestHeader("Content-type", | |
"application/x-www-form-urlencoded"); | |
} | |
xhr.onreadystatechange = function() { | |
if(xhr.readyState == 4) { | |
if(xhr.status == 200) { | |
B(A(cb,[[1,[0,xhr.responseText]],0])); | |
} else { | |
B(A(cb,[[0],0])); // Nothing | |
} | |
} | |
} | |
xhr.send(postdata); | |
} | |
// Create a little endian ArrayBuffer representation of something. | |
function toABHost(v, n, x) { | |
var a = new ArrayBuffer(n); | |
new window[v](a)[0] = x; | |
return a; | |
} | |
function toABSwap(v, n, x) { | |
var a = new ArrayBuffer(n); | |
new window[v](a)[0] = x; | |
var bs = new Uint8Array(a); | |
for(var i = 0, j = n-1; i < j; ++i, --j) { | |
var tmp = bs[i]; | |
bs[i] = bs[j]; | |
bs[j] = tmp; | |
} | |
return a; | |
} | |
window['toABle'] = toABHost; | |
window['toABbe'] = toABSwap; | |
// Swap byte order if host is not little endian. | |
var buffer = new ArrayBuffer(2); | |
new DataView(buffer).setInt16(0, 256, true); | |
if(new Int16Array(buffer)[0] !== 256) { | |
window['toABle'] = toABSwap; | |
window['toABbe'] = toABHost; | |
} | |
// MVar implementation. | |
// Since Haste isn't concurrent, takeMVar and putMVar don't block on empty | |
// and full MVars respectively, but terminate the program since they would | |
// otherwise be blocking forever. | |
function newMVar() { | |
return ({empty: true}); | |
} | |
function tryTakeMVar(mv) { | |
if(mv.empty) { | |
return [0, 0, undefined]; | |
} else { | |
var val = mv.x; | |
mv.empty = true; | |
mv.x = null; | |
return [0, 1, val]; | |
} | |
} | |
function takeMVar(mv) { | |
if(mv.empty) { | |
// TODO: real BlockedOnDeadMVar exception, perhaps? | |
err("Attempted to take empty MVar!"); | |
} | |
var val = mv.x; | |
mv.empty = true; | |
mv.x = null; | |
return val; | |
} | |
function putMVar(mv, val) { | |
if(!mv.empty) { | |
// TODO: real BlockedOnDeadMVar exception, perhaps? | |
err("Attempted to put full MVar!"); | |
} | |
mv.empty = false; | |
mv.x = val; | |
} | |
function tryPutMVar(mv, val) { | |
if(!mv.empty) { | |
return 0; | |
} else { | |
mv.empty = false; | |
mv.x = val; | |
return 1; | |
} | |
} | |
function sameMVar(a, b) { | |
return (a == b); | |
} | |
function isEmptyMVar(mv) { | |
return mv.empty ? 1 : 0; | |
} | |
// Implementation of stable names. | |
// Unlike native GHC, the garbage collector isn't going to move data around | |
// in a way that we can detect, so each object could serve as its own stable | |
// name if it weren't for the fact we can't turn a JS reference into an | |
// integer. | |
// So instead, each object has a unique integer attached to it, which serves | |
// as its stable name. | |
var __next_stable_name = 1; | |
function makeStableName(x) { | |
if(!x.stableName) { | |
x.stableName = __next_stable_name; | |
__next_stable_name += 1; | |
} | |
return x.stableName; | |
} | |
function eqStableName(x, y) { | |
return (x == y) ? 1 : 0; | |
} | |
var Integer = function(bits, sign) { | |
this.bits_ = []; | |
this.sign_ = sign; | |
var top = true; | |
for (var i = bits.length - 1; i >= 0; i--) { | |
var val = bits[i] | 0; | |
if (!top || val != sign) { | |
this.bits_[i] = val; | |
top = false; | |
} | |
} | |
}; | |
Integer.IntCache_ = {}; | |
var I_fromInt = function(value) { | |
if (-128 <= value && value < 128) { | |
var cachedObj = Integer.IntCache_[value]; | |
if (cachedObj) { | |
return cachedObj; | |
} | |
} | |
var obj = new Integer([value | 0], value < 0 ? -1 : 0); | |
if (-128 <= value && value < 128) { | |
Integer.IntCache_[value] = obj; | |
} | |
return obj; | |
}; | |
var I_fromNumber = function(value) { | |
if (isNaN(value) || !isFinite(value)) { | |
return Integer.ZERO; | |
} else if (value < 0) { | |
return I_negate(I_fromNumber(-value)); | |
} else { | |
var bits = []; | |
var pow = 1; | |
for (var i = 0; value >= pow; i++) { | |
bits[i] = (value / pow) | 0; | |
pow *= Integer.TWO_PWR_32_DBL_; | |
} | |
return new Integer(bits, 0); | |
} | |
}; | |
var I_fromBits = function(bits) { | |
var high = bits[bits.length - 1]; | |
return new Integer(bits, high & (1 << 31) ? -1 : 0); | |
}; | |
var I_fromString = function(str, opt_radix) { | |
if (str.length == 0) { | |
throw Error('number format error: empty string'); | |
} | |
var radix = opt_radix || 10; | |
if (radix < 2 || 36 < radix) { | |
throw Error('radix out of range: ' + radix); | |
} | |
if (str.charAt(0) == '-') { | |
return I_negate(I_fromString(str.substring(1), radix)); | |
} else if (str.indexOf('-') >= 0) { | |
throw Error('number format error: interior "-" character'); | |
} | |
var radixToPower = I_fromNumber(Math.pow(radix, 8)); | |
var result = Integer.ZERO; | |
for (var i = 0; i < str.length; i += 8) { | |
var size = Math.min(8, str.length - i); | |
var value = parseInt(str.substring(i, i + size), radix); | |
if (size < 8) { | |
var power = I_fromNumber(Math.pow(radix, size)); | |
result = I_add(I_mul(result, power), I_fromNumber(value)); | |
} else { | |
result = I_mul(result, radixToPower); | |
result = I_add(result, I_fromNumber(value)); | |
} | |
} | |
return result; | |
}; | |
Integer.TWO_PWR_32_DBL_ = (1 << 16) * (1 << 16); | |
Integer.ZERO = I_fromInt(0); | |
Integer.ONE = I_fromInt(1); | |
Integer.TWO_PWR_24_ = I_fromInt(1 << 24); | |
var I_toInt = function(self) { | |
return self.bits_.length > 0 ? self.bits_[0] : self.sign_; | |
}; | |
var I_toWord = function(self) { | |
return I_toInt(self) >>> 0; | |
}; | |
var I_toNumber = function(self) { | |
if (isNegative(self)) { | |
return -I_toNumber(I_negate(self)); | |
} else { | |
var val = 0; | |
var pow = 1; | |
for (var i = 0; i < self.bits_.length; i++) { | |
val += I_getBitsUnsigned(self, i) * pow; | |
pow *= Integer.TWO_PWR_32_DBL_; | |
} | |
return val; | |
} | |
}; | |
var I_getBits = function(self, index) { | |
if (index < 0) { | |
return 0; | |
} else if (index < self.bits_.length) { | |
return self.bits_[index]; | |
} else { | |
return self.sign_; | |
} | |
}; | |
var I_getBitsUnsigned = function(self, index) { | |
var val = I_getBits(self, index); | |
return val >= 0 ? val : Integer.TWO_PWR_32_DBL_ + val; | |
}; | |
var getSign = function(self) { | |
return self.sign_; | |
}; | |
var isZero = function(self) { | |
if (self.sign_ != 0) { | |
return false; | |
} | |
for (var i = 0; i < self.bits_.length; i++) { | |
if (self.bits_[i] != 0) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
var isNegative = function(self) { | |
return self.sign_ == -1; | |
}; | |
var isOdd = function(self) { | |
return (self.bits_.length == 0) && (self.sign_ == -1) || | |
(self.bits_.length > 0) && ((self.bits_[0] & 1) != 0); | |
}; | |
var I_equals = function(self, other) { | |
if (self.sign_ != other.sign_) { | |
return false; | |
} | |
var len = Math.max(self.bits_.length, other.bits_.length); | |
for (var i = 0; i < len; i++) { | |
if (I_getBits(self, i) != I_getBits(other, i)) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
var I_notEquals = function(self, other) { | |
return !I_equals(self, other); | |
}; | |
var I_greaterThan = function(self, other) { | |
return I_compare(self, other) > 0; | |
}; | |
var I_greaterThanOrEqual = function(self, other) { | |
return I_compare(self, other) >= 0; | |
}; | |
var I_lessThan = function(self, other) { | |
return I_compare(self, other) < 0; | |
}; | |
var I_lessThanOrEqual = function(self, other) { | |
return I_compare(self, other) <= 0; | |
}; | |
var I_compare = function(self, other) { | |
var diff = I_sub(self, other); | |
if (isNegative(diff)) { | |
return -1; | |
} else if (isZero(diff)) { | |
return 0; | |
} else { | |
return +1; | |
} | |
}; | |
var I_compareInt = function(self, other) { | |
return I_compare(self, I_fromInt(other)); | |
} | |
var shorten = function(self, numBits) { | |
var arr_index = (numBits - 1) >> 5; | |
var bit_index = (numBits - 1) % 32; | |
var bits = []; | |
for (var i = 0; i < arr_index; i++) { | |
bits[i] = I_getBits(self, i); | |
} | |
var sigBits = bit_index == 31 ? 0xFFFFFFFF : (1 << (bit_index + 1)) - 1; | |
var val = I_getBits(self, arr_index) & sigBits; | |
if (val & (1 << bit_index)) { | |
val |= 0xFFFFFFFF - sigBits; | |
bits[arr_index] = val; | |
return new Integer(bits, -1); | |
} else { | |
bits[arr_index] = val; | |
return new Integer(bits, 0); | |
} | |
}; | |
var I_negate = function(self) { | |
return I_add(not(self), Integer.ONE); | |
}; | |
var I_add = function(self, other) { | |
var len = Math.max(self.bits_.length, other.bits_.length); | |
var arr = []; | |
var carry = 0; | |
for (var i = 0; i <= len; i++) { | |
var a1 = I_getBits(self, i) >>> 16; | |
var a0 = I_getBits(self, i) & 0xFFFF; | |
var b1 = I_getBits(other, i) >>> 16; | |
var b0 = I_getBits(other, i) & 0xFFFF; | |
var c0 = carry + a0 + b0; | |
var c1 = (c0 >>> 16) + a1 + b1; | |
carry = c1 >>> 16; | |
c0 &= 0xFFFF; | |
c1 &= 0xFFFF; | |
arr[i] = (c1 << 16) | c0; | |
} | |
return I_fromBits(arr); | |
}; | |
var I_sub = function(self, other) { | |
return I_add(self, I_negate(other)); | |
}; | |
var I_mul = function(self, other) { | |
if (isZero(self)) { | |
return Integer.ZERO; | |
} else if (isZero(other)) { | |
return Integer.ZERO; | |
} | |
if (isNegative(self)) { | |
if (isNegative(other)) { | |
return I_mul(I_negate(self), I_negate(other)); | |
} else { | |
return I_negate(I_mul(I_negate(self), other)); | |
} | |
} else if (isNegative(other)) { | |
return I_negate(I_mul(self, I_negate(other))); | |
} | |
if (I_lessThan(self, Integer.TWO_PWR_24_) && | |
I_lessThan(other, Integer.TWO_PWR_24_)) { | |
return I_fromNumber(I_toNumber(self) * I_toNumber(other)); | |
} | |
var len = self.bits_.length + other.bits_.length; | |
var arr = []; | |
for (var i = 0; i < 2 * len; i++) { | |
arr[i] = 0; | |
} | |
for (var i = 0; i < self.bits_.length; i++) { | |
for (var j = 0; j < other.bits_.length; j++) { | |
var a1 = I_getBits(self, i) >>> 16; | |
var a0 = I_getBits(self, i) & 0xFFFF; | |
var b1 = I_getBits(other, j) >>> 16; | |
var b0 = I_getBits(other, j) & 0xFFFF; | |
arr[2 * i + 2 * j] += a0 * b0; | |
Integer.carry16_(arr, 2 * i + 2 * j); | |
arr[2 * i + 2 * j + 1] += a1 * b0; | |
Integer.carry16_(arr, 2 * i + 2 * j + 1); | |
arr[2 * i + 2 * j + 1] += a0 * b1; | |
Integer.carry16_(arr, 2 * i + 2 * j + 1); | |
arr[2 * i + 2 * j + 2] += a1 * b1; | |
Integer.carry16_(arr, 2 * i + 2 * j + 2); | |
} | |
} | |
for (var i = 0; i < len; i++) { | |
arr[i] = (arr[2 * i + 1] << 16) | arr[2 * i]; | |
} | |
for (var i = len; i < 2 * len; i++) { | |
arr[i] = 0; | |
} | |
return new Integer(arr, 0); | |
}; | |
Integer.carry16_ = function(bits, index) { | |
while ((bits[index] & 0xFFFF) != bits[index]) { | |
bits[index + 1] += bits[index] >>> 16; | |
bits[index] &= 0xFFFF; | |
} | |
}; | |
var I_mod = function(self, other) { | |
return I_rem(I_add(other, I_rem(self, other)), other); | |
} | |
var I_div = function(self, other) { | |
if(I_greaterThan(self, Integer.ZERO) != I_greaterThan(other, Integer.ZERO)) { | |
if(I_rem(self, other) != Integer.ZERO) { | |
return I_sub(I_quot(self, other), Integer.ONE); | |
} | |
} | |
return I_quot(self, other); | |
} | |
var I_quotRem = function(self, other) { | |
return [0, I_quot(self, other), I_rem(self, other)]; | |
} | |
var I_divMod = function(self, other) { | |
return [0, I_div(self, other), I_mod(self, other)]; | |
} | |
var I_quot = function(self, other) { | |
if (isZero(other)) { | |
throw Error('division by zero'); | |
} else if (isZero(self)) { | |
return Integer.ZERO; | |
} | |
if (isNegative(self)) { | |
if (isNegative(other)) { | |
return I_quot(I_negate(self), I_negate(other)); | |
} else { | |
return I_negate(I_quot(I_negate(self), other)); | |
} | |
} else if (isNegative(other)) { | |
return I_negate(I_quot(self, I_negate(other))); | |
} | |
var res = Integer.ZERO; | |
var rem = self; | |
while (I_greaterThanOrEqual(rem, other)) { | |
var approx = Math.max(1, Math.floor(I_toNumber(rem) / I_toNumber(other))); | |
var log2 = Math.ceil(Math.log(approx) / Math.LN2); | |
var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); | |
var approxRes = I_fromNumber(approx); | |
var approxRem = I_mul(approxRes, other); | |
while (isNegative(approxRem) || I_greaterThan(approxRem, rem)) { | |
approx -= delta; | |
approxRes = I_fromNumber(approx); | |
approxRem = I_mul(approxRes, other); | |
} | |
if (isZero(approxRes)) { | |
approxRes = Integer.ONE; | |
} | |
res = I_add(res, approxRes); | |
rem = I_sub(rem, approxRem); | |
} | |
return res; | |
}; | |
var I_rem = function(self, other) { | |
return I_sub(self, I_mul(I_quot(self, other), other)); | |
}; | |
var not = function(self) { | |
var len = self.bits_.length; | |
var arr = []; | |
for (var i = 0; i < len; i++) { | |
arr[i] = ~self.bits_[i]; | |
} | |
return new Integer(arr, ~self.sign_); | |
}; | |
var I_and = function(self, other) { | |
var len = Math.max(self.bits_.length, other.bits_.length); | |
var arr = []; | |
for (var i = 0; i < len; i++) { | |
arr[i] = I_getBits(self, i) & I_getBits(other, i); | |
} | |
return new Integer(arr, self.sign_ & other.sign_); | |
}; | |
var I_or = function(self, other) { | |
var len = Math.max(self.bits_.length, other.bits_.length); | |
var arr = []; | |
for (var i = 0; i < len; i++) { | |
arr[i] = I_getBits(self, i) | I_getBits(other, i); | |
} | |
return new Integer(arr, self.sign_ | other.sign_); | |
}; | |
var I_xor = function(self, other) { | |
var len = Math.max(self.bits_.length, other.bits_.length); | |
var arr = []; | |
for (var i = 0; i < len; i++) { | |
arr[i] = I_getBits(self, i) ^ I_getBits(other, i); | |
} | |
return new Integer(arr, self.sign_ ^ other.sign_); | |
}; | |
var I_shiftLeft = function(self, numBits) { | |
var arr_delta = numBits >> 5; | |
var bit_delta = numBits % 32; | |
var len = self.bits_.length + arr_delta + (bit_delta > 0 ? 1 : 0); | |
var arr = []; | |
for (var i = 0; i < len; i++) { | |
if (bit_delta > 0) { | |
arr[i] = (I_getBits(self, i - arr_delta) << bit_delta) | | |
(I_getBits(self, i - arr_delta - 1) >>> (32 - bit_delta)); | |
} else { | |
arr[i] = I_getBits(self, i - arr_delta); | |
} | |
} | |
return new Integer(arr, self.sign_); | |
}; | |
var I_shiftRight = function(self, numBits) { | |
var arr_delta = numBits >> 5; | |
var bit_delta = numBits % 32; | |
var len = self.bits_.length - arr_delta; | |
var arr = []; | |
for (var i = 0; i < len; i++) { | |
if (bit_delta > 0) { | |
arr[i] = (I_getBits(self, i + arr_delta) >>> bit_delta) | | |
(I_getBits(self, i + arr_delta + 1) << (32 - bit_delta)); | |
} else { | |
arr[i] = I_getBits(self, i + arr_delta); | |
} | |
} | |
return new Integer(arr, self.sign_); | |
}; | |
var I_signum = function(self) { | |
var cmp = I_compare(self, Integer.ZERO); | |
if(cmp > 0) { | |
return Integer.ONE | |
} | |
if(cmp < 0) { | |
return I_sub(Integer.ZERO, Integer.ONE); | |
} | |
return Integer.ZERO; | |
}; | |
var I_abs = function(self) { | |
if(I_compare(self, Integer.ZERO) < 0) { | |
return I_sub(Integer.ZERO, self); | |
} | |
return self; | |
}; | |
var I_decodeDouble = function(x) { | |
var dec = decodeDouble(x); | |
var mantissa = I_fromBits([dec[3], dec[2]]); | |
if(dec[1] < 0) { | |
mantissa = I_negate(mantissa); | |
} | |
return [0, dec[4], mantissa]; | |
} | |
var I_toString = function(self) { | |
var radix = 10; | |
if (isZero(self)) { | |
return '0'; | |
} else if (isNegative(self)) { | |
return '-' + I_toString(I_negate(self)); | |
} | |
var radixToPower = I_fromNumber(Math.pow(radix, 6)); | |
var rem = self; | |
var result = ''; | |
while (true) { | |
var remDiv = I_div(rem, radixToPower); | |
var intval = I_toInt(I_sub(rem, I_mul(remDiv, radixToPower))); | |
var digits = intval.toString(); | |
rem = remDiv; | |
if (isZero(rem)) { | |
return digits + result; | |
} else { | |
while (digits.length < 6) { | |
digits = '0' + digits; | |
} | |
result = '' + digits + result; | |
} | |
} | |
}; | |
var I_fromRat = function(a, b) { | |
return I_toNumber(a) / I_toNumber(b); | |
} | |
function I_fromInt64(x) { | |
return I_fromBits([x.getLowBits(), x.getHighBits()]); | |
} | |
function I_toInt64(x) { | |
return Long.fromBits(I_getBits(x, 0), I_getBits(x, 1)); | |
} | |
function I_fromWord64(x) { | |
return x; | |
} | |
function I_toWord64(x) { | |
return I_rem(I_add(__w64_max, x), __w64_max); | |
} | |
// Copyright 2009 The Closure Library Authors. All Rights Reserved. | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS-IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
var Long = function(low, high) { | |
this.low_ = low | 0; | |
this.high_ = high | 0; | |
}; | |
Long.IntCache_ = {}; | |
Long.fromInt = function(value) { | |
if (-128 <= value && value < 128) { | |
var cachedObj = Long.IntCache_[value]; | |
if (cachedObj) { | |
return cachedObj; | |
} | |
} | |
var obj = new Long(value | 0, value < 0 ? -1 : 0); | |
if (-128 <= value && value < 128) { | |
Long.IntCache_[value] = obj; | |
} | |
return obj; | |
}; | |
Long.fromNumber = function(value) { | |
if (isNaN(value) || !isFinite(value)) { | |
return Long.ZERO; | |
} else if (value <= -Long.TWO_PWR_63_DBL_) { | |
return Long.MIN_VALUE; | |
} else if (value + 1 >= Long.TWO_PWR_63_DBL_) { | |
return Long.MAX_VALUE; | |
} else if (value < 0) { | |
return Long.fromNumber(-value).negate(); | |
} else { | |
return new Long( | |
(value % Long.TWO_PWR_32_DBL_) | 0, | |
(value / Long.TWO_PWR_32_DBL_) | 0); | |
} | |
}; | |
Long.fromBits = function(lowBits, highBits) { | |
return new Long(lowBits, highBits); | |
}; | |
Long.TWO_PWR_16_DBL_ = 1 << 16; | |
Long.TWO_PWR_24_DBL_ = 1 << 24; | |
Long.TWO_PWR_32_DBL_ = | |
Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_; | |
Long.TWO_PWR_31_DBL_ = | |
Long.TWO_PWR_32_DBL_ / 2; | |
Long.TWO_PWR_48_DBL_ = | |
Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_; | |
Long.TWO_PWR_64_DBL_ = | |
Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_; | |
Long.TWO_PWR_63_DBL_ = | |
Long.TWO_PWR_64_DBL_ / 2; | |
Long.ZERO = Long.fromInt(0); | |
Long.ONE = Long.fromInt(1); | |
Long.NEG_ONE = Long.fromInt(-1); | |
Long.MAX_VALUE = | |
Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); | |
Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0); | |
Long.TWO_PWR_24_ = Long.fromInt(1 << 24); | |
Long.prototype.toInt = function() { | |
return this.low_; | |
}; | |
Long.prototype.toNumber = function() { | |
return this.high_ * Long.TWO_PWR_32_DBL_ + | |
this.getLowBitsUnsigned(); | |
}; | |
Long.prototype.getHighBits = function() { | |
return this.high_; | |
}; | |
Long.prototype.getLowBits = function() { | |
return this.low_; | |
}; | |
Long.prototype.getLowBitsUnsigned = function() { | |
return (this.low_ >= 0) ? | |
this.low_ : Long.TWO_PWR_32_DBL_ + this.low_; | |
}; | |
Long.prototype.isZero = function() { | |
return this.high_ == 0 && this.low_ == 0; | |
}; | |
Long.prototype.isNegative = function() { | |
return this.high_ < 0; | |
}; | |
Long.prototype.isOdd = function() { | |
return (this.low_ & 1) == 1; | |
}; | |
Long.prototype.equals = function(other) { | |
return (this.high_ == other.high_) && (this.low_ == other.low_); | |
}; | |
Long.prototype.notEquals = function(other) { | |
return (this.high_ != other.high_) || (this.low_ != other.low_); | |
}; | |
Long.prototype.lessThan = function(other) { | |
return this.compare(other) < 0; | |
}; | |
Long.prototype.lessThanOrEqual = function(other) { | |
return this.compare(other) <= 0; | |
}; | |
Long.prototype.greaterThan = function(other) { | |
return this.compare(other) > 0; | |
}; | |
Long.prototype.greaterThanOrEqual = function(other) { | |
return this.compare(other) >= 0; | |
}; | |
Long.prototype.compare = function(other) { | |
if (this.equals(other)) { | |
return 0; | |
} | |
var thisNeg = this.isNegative(); | |
var otherNeg = other.isNegative(); | |
if (thisNeg && !otherNeg) { | |
return -1; | |
} | |
if (!thisNeg && otherNeg) { | |
return 1; | |
} | |
if (this.subtract(other).isNegative()) { | |
return -1; | |
} else { | |
return 1; | |
} | |
}; | |
Long.prototype.negate = function() { | |
if (this.equals(Long.MIN_VALUE)) { | |
return Long.MIN_VALUE; | |
} else { | |
return this.not().add(Long.ONE); | |
} | |
}; | |
Long.prototype.add = function(other) { | |
var a48 = this.high_ >>> 16; | |
var a32 = this.high_ & 0xFFFF; | |
var a16 = this.low_ >>> 16; | |
var a00 = this.low_ & 0xFFFF; | |
var b48 = other.high_ >>> 16; | |
var b32 = other.high_ & 0xFFFF; | |
var b16 = other.low_ >>> 16; | |
var b00 = other.low_ & 0xFFFF; | |
var c48 = 0, c32 = 0, c16 = 0, c00 = 0; | |
c00 += a00 + b00; | |
c16 += c00 >>> 16; | |
c00 &= 0xFFFF; | |
c16 += a16 + b16; | |
c32 += c16 >>> 16; | |
c16 &= 0xFFFF; | |
c32 += a32 + b32; | |
c48 += c32 >>> 16; | |
c32 &= 0xFFFF; | |
c48 += a48 + b48; | |
c48 &= 0xFFFF; | |
return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); | |
}; | |
Long.prototype.subtract = function(other) { | |
return this.add(other.negate()); | |
}; | |
Long.prototype.multiply = function(other) { | |
if (this.isZero()) { | |
return Long.ZERO; | |
} else if (other.isZero()) { | |
return Long.ZERO; | |
} | |
if (this.equals(Long.MIN_VALUE)) { | |
return other.isOdd() ? Long.MIN_VALUE : Long.ZERO; | |
} else if (other.equals(Long.MIN_VALUE)) { | |
return this.isOdd() ? Long.MIN_VALUE : Long.ZERO; | |
} | |
if (this.isNegative()) { | |
if (other.isNegative()) { | |
return this.negate().multiply(other.negate()); | |
} else { | |
return this.negate().multiply(other).negate(); | |
} | |
} else if (other.isNegative()) { | |
return this.multiply(other.negate()).negate(); | |
} | |
if (this.lessThan(Long.TWO_PWR_24_) && | |
other.lessThan(Long.TWO_PWR_24_)) { | |
return Long.fromNumber(this.toNumber() * other.toNumber()); | |
} | |
var a48 = this.high_ >>> 16; | |
var a32 = this.high_ & 0xFFFF; | |
var a16 = this.low_ >>> 16; | |
var a00 = this.low_ & 0xFFFF; | |
var b48 = other.high_ >>> 16; | |
var b32 = other.high_ & 0xFFFF; | |
var b16 = other.low_ >>> 16; | |
var b00 = other.low_ & 0xFFFF; | |
var c48 = 0, c32 = 0, c16 = 0, c00 = 0; | |
c00 += a00 * b00; | |
c16 += c00 >>> 16; | |
c00 &= 0xFFFF; | |
c16 += a16 * b00; | |
c32 += c16 >>> 16; | |
c16 &= 0xFFFF; | |
c16 += a00 * b16; | |
c32 += c16 >>> 16; | |
c16 &= 0xFFFF; | |
c32 += a32 * b00; | |
c48 += c32 >>> 16; | |
c32 &= 0xFFFF; | |
c32 += a16 * b16; | |
c48 += c32 >>> 16; | |
c32 &= 0xFFFF; | |
c32 += a00 * b32; | |
c48 += c32 >>> 16; | |
c32 &= 0xFFFF; | |
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; | |
c48 &= 0xFFFF; | |
return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); | |
}; | |
Long.prototype.div = function(other) { | |
if (other.isZero()) { | |
throw Error('division by zero'); | |
} else if (this.isZero()) { | |
return Long.ZERO; | |
} | |
if (this.equals(Long.MIN_VALUE)) { | |
if (other.equals(Long.ONE) || | |
other.equals(Long.NEG_ONE)) { | |
return Long.MIN_VALUE; | |
} else if (other.equals(Long.MIN_VALUE)) { | |
return Long.ONE; | |
} else { | |
var halfThis = this.shiftRight(1); | |
var approx = halfThis.div(other).shiftLeft(1); | |
if (approx.equals(Long.ZERO)) { | |
return other.isNegative() ? Long.ONE : Long.NEG_ONE; | |
} else { | |
var rem = this.subtract(other.multiply(approx)); | |
var result = approx.add(rem.div(other)); | |
return result; | |
} | |
} | |
} else if (other.equals(Long.MIN_VALUE)) { | |
return Long.ZERO; | |
} | |
if (this.isNegative()) { | |
if (other.isNegative()) { | |
return this.negate().div(other.negate()); | |
} else { | |
return this.negate().div(other).negate(); | |
} | |
} else if (other.isNegative()) { | |
return this.div(other.negate()).negate(); | |
} | |
var res = Long.ZERO; | |
var rem = this; | |
while (rem.greaterThanOrEqual(other)) { | |
var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); | |
var log2 = Math.ceil(Math.log(approx) / Math.LN2); | |
var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); | |
var approxRes = Long.fromNumber(approx); | |
var approxRem = approxRes.multiply(other); | |
while (approxRem.isNegative() || approxRem.greaterThan(rem)) { | |
approx -= delta; | |
approxRes = Long.fromNumber(approx); | |
approxRem = approxRes.multiply(other); | |
} | |
if (approxRes.isZero()) { | |
approxRes = Long.ONE; | |
} | |
res = res.add(approxRes); | |
rem = rem.subtract(approxRem); | |
} | |
return res; | |
}; | |
Long.prototype.modulo = function(other) { | |
return this.subtract(this.div(other).multiply(other)); | |
}; | |
Long.prototype.not = function() { | |
return Long.fromBits(~this.low_, ~this.high_); | |
}; | |
Long.prototype.and = function(other) { | |
return Long.fromBits(this.low_ & other.low_, | |
this.high_ & other.high_); | |
}; | |
Long.prototype.or = function(other) { | |
return Long.fromBits(this.low_ | other.low_, | |
this.high_ | other.high_); | |
}; | |
Long.prototype.xor = function(other) { | |
return Long.fromBits(this.low_ ^ other.low_, | |
this.high_ ^ other.high_); | |
}; | |
Long.prototype.shiftLeft = function(numBits) { | |
numBits &= 63; | |
if (numBits == 0) { | |
return this; | |
} else { | |
var low = this.low_; | |
if (numBits < 32) { | |
var high = this.high_; | |
return Long.fromBits( | |
low << numBits, | |
(high << numBits) | (low >>> (32 - numBits))); | |
} else { | |
return Long.fromBits(0, low << (numBits - 32)); | |
} | |
} | |
}; | |
Long.prototype.shiftRight = function(numBits) { | |
numBits &= 63; | |
if (numBits == 0) { | |
return this; | |
} else { | |
var high = this.high_; | |
if (numBits < 32) { | |
var low = this.low_; | |
return Long.fromBits( | |
(low >>> numBits) | (high << (32 - numBits)), | |
high >> numBits); | |
} else { | |
return Long.fromBits( | |
high >> (numBits - 32), | |
high >= 0 ? 0 : -1); | |
} | |
} | |
}; | |
Long.prototype.shiftRightUnsigned = function(numBits) { | |
numBits &= 63; | |
if (numBits == 0) { | |
return this; | |
} else { | |
var high = this.high_; | |
if (numBits < 32) { | |
var low = this.low_; | |
return Long.fromBits( | |
(low >>> numBits) | (high << (32 - numBits)), | |
high >>> numBits); | |
} else if (numBits == 32) { | |
return Long.fromBits(high, 0); | |
} else { | |
return Long.fromBits(high >>> (numBits - 32), 0); | |
} | |
} | |
}; | |
// Int64 | |
function hs_eqInt64(x, y) {return x.equals(y);} | |
function hs_neInt64(x, y) {return !x.equals(y);} | |
function hs_ltInt64(x, y) {return x.compare(y) < 0;} | |
function hs_leInt64(x, y) {return x.compare(y) <= 0;} | |
function hs_gtInt64(x, y) {return x.compare(y) > 0;} | |
function hs_geInt64(x, y) {return x.compare(y) >= 0;} | |
function hs_quotInt64(x, y) {return x.div(y);} | |
function hs_remInt64(x, y) {return x.modulo(y);} | |
function hs_plusInt64(x, y) {return x.add(y);} | |
function hs_minusInt64(x, y) {return x.subtract(y);} | |
function hs_timesInt64(x, y) {return x.multiply(y);} | |
function hs_negateInt64(x) {return x.negate();} | |
function hs_uncheckedIShiftL64(x, bits) {return x.shiftLeft(bits);} | |
function hs_uncheckedIShiftRA64(x, bits) {return x.shiftRight(bits);} | |
function hs_uncheckedIShiftRL64(x, bits) {return x.shiftRightUnsigned(bits);} | |
function hs_intToInt64(x) {return new Long(x, 0);} | |
function hs_int64ToInt(x) {return x.toInt();} | |
// Word64 | |
function hs_wordToWord64(x) { | |
return I_fromInt(x); | |
} | |
function hs_word64ToWord(x) { | |
return I_toInt(x); | |
} | |
function hs_mkWord64(low, high) { | |
return I_fromBits([low, high]); | |
} | |
var hs_and64 = I_and; | |
var hs_or64 = I_or; | |
var hs_xor64 = I_xor; | |
var __i64_all_ones = I_fromBits([0xffffffff, 0xffffffff]); | |
function hs_not64(x) { | |
return I_xor(x, __i64_all_ones); | |
} | |
var hs_eqWord64 = I_equals; | |
var hs_neWord64 = I_notEquals; | |
var hs_ltWord64 = I_lessThan; | |
var hs_leWord64 = I_lessThanOrEqual; | |
var hs_gtWord64 = I_greaterThan; | |
var hs_geWord64 = I_greaterThanOrEqual; | |
var hs_quotWord64 = I_quot; | |
var hs_remWord64 = I_rem; | |
var __w64_max = I_fromBits([0,0,1]); | |
function hs_uncheckedShiftL64(x, bits) { | |
return I_rem(I_shiftLeft(x, bits), __w64_max); | |
} | |
var hs_uncheckedShiftRL64 = I_shiftRight; | |
function hs_int64ToWord64(x) { | |
var tmp = I_add(__w64_max, I_fromBits([x.getLowBits(), x.getHighBits()])); | |
return I_rem(tmp, __w64_max); | |
} | |
function hs_word64ToInt64(x) { | |
return Long.fromBits(I_getBits(x, 0), I_getBits(x, 1)); | |
} | |
// Joseph Myers' MD5 implementation; used under the BSD license. | |
function md5cycle(x, k) { | |
var a = x[0], b = x[1], c = x[2], d = x[3]; | |
a = ff(a, b, c, d, k[0], 7, -680876936); | |
d = ff(d, a, b, c, k[1], 12, -389564586); | |
c = ff(c, d, a, b, k[2], 17, 606105819); | |
b = ff(b, c, d, a, k[3], 22, -1044525330); | |
a = ff(a, b, c, d, k[4], 7, -176418897); | |
d = ff(d, a, b, c, k[5], 12, 1200080426); | |
c = ff(c, d, a, b, k[6], 17, -1473231341); | |
b = ff(b, c, d, a, k[7], 22, -45705983); | |
a = ff(a, b, c, d, k[8], 7, 1770035416); | |
d = ff(d, a, b, c, k[9], 12, -1958414417); | |
c = ff(c, d, a, b, k[10], 17, -42063); | |
b = ff(b, c, d, a, k[11], 22, -1990404162); | |
a = ff(a, b, c, d, k[12], 7, 1804603682); | |
d = ff(d, a, b, c, k[13], 12, -40341101); | |
c = ff(c, d, a, b, k[14], 17, -1502002290); | |
b = ff(b, c, d, a, k[15], 22, 1236535329); | |
a = gg(a, b, c, d, k[1], 5, -165796510); | |
d = gg(d, a, b, c, k[6], 9, -1069501632); | |
c = gg(c, d, a, b, k[11], 14, 643717713); | |
b = gg(b, c, d, a, k[0], 20, -373897302); | |
a = gg(a, b, c, d, k[5], 5, -701558691); | |
d = gg(d, a, b, c, k[10], 9, 38016083); | |
c = gg(c, d, a, b, k[15], 14, -660478335); | |
b = gg(b, c, d, a, k[4], 20, -405537848); | |
a = gg(a, b, c, d, k[9], 5, 568446438); | |
d = gg(d, a, b, c, k[14], 9, -1019803690); | |
c = gg(c, d, a, b, k[3], 14, -187363961); | |
b = gg(b, c, d, a, k[8], 20, 1163531501); | |
a = gg(a, b, c, d, k[13], 5, -1444681467); | |
d = gg(d, a, b, c, k[2], 9, -51403784); | |
c = gg(c, d, a, b, k[7], 14, 1735328473); | |
b = gg(b, c, d, a, k[12], 20, -1926607734); | |
a = hh(a, b, c, d, k[5], 4, -378558); | |
d = hh(d, a, b, c, k[8], 11, -2022574463); | |
c = hh(c, d, a, b, k[11], 16, 1839030562); | |
b = hh(b, c, d, a, k[14], 23, -35309556); | |
a = hh(a, b, c, d, k[1], 4, -1530992060); | |
d = hh(d, a, b, c, k[4], 11, 1272893353); | |
c = hh(c, d, a, b, k[7], 16, -155497632); | |
b = hh(b, c, d, a, k[10], 23, -1094730640); | |
a = hh(a, b, c, d, k[13], 4, 681279174); | |
d = hh(d, a, b, c, k[0], 11, -358537222); | |
c = hh(c, d, a, b, k[3], 16, -722521979); | |
b = hh(b, c, d, a, k[6], 23, 76029189); | |
a = hh(a, b, c, d, k[9], 4, -640364487); | |
d = hh(d, a, b, c, k[12], 11, -421815835); | |
c = hh(c, d, a, b, k[15], 16, 530742520); | |
b = hh(b, c, d, a, k[2], 23, -995338651); | |
a = ii(a, b, c, d, k[0], 6, -198630844); | |
d = ii(d, a, b, c, k[7], 10, 1126891415); | |
c = ii(c, d, a, b, k[14], 15, -1416354905); | |
b = ii(b, c, d, a, k[5], 21, -57434055); | |
a = ii(a, b, c, d, k[12], 6, 1700485571); | |
d = ii(d, a, b, c, k[3], 10, -1894986606); | |
c = ii(c, d, a, b, k[10], 15, -1051523); | |
b = ii(b, c, d, a, k[1], 21, -2054922799); | |
a = ii(a, b, c, d, k[8], 6, 1873313359); | |
d = ii(d, a, b, c, k[15], 10, -30611744); | |
c = ii(c, d, a, b, k[6], 15, -1560198380); | |
b = ii(b, c, d, a, k[13], 21, 1309151649); | |
a = ii(a, b, c, d, k[4], 6, -145523070); | |
d = ii(d, a, b, c, k[11], 10, -1120210379); | |
c = ii(c, d, a, b, k[2], 15, 718787259); | |
b = ii(b, c, d, a, k[9], 21, -343485551); | |
x[0] = add32(a, x[0]); | |
x[1] = add32(b, x[1]); | |
x[2] = add32(c, x[2]); | |
x[3] = add32(d, x[3]); | |
} | |
function cmn(q, a, b, x, s, t) { | |
a = add32(add32(a, q), add32(x, t)); | |
return add32((a << s) | (a >>> (32 - s)), b); | |
} | |
function ff(a, b, c, d, x, s, t) { | |
return cmn((b & c) | ((~b) & d), a, b, x, s, t); | |
} | |
function gg(a, b, c, d, x, s, t) { | |
return cmn((b & d) | (c & (~d)), a, b, x, s, t); | |
} | |
function hh(a, b, c, d, x, s, t) { | |
return cmn(b ^ c ^ d, a, b, x, s, t); | |
} | |
function ii(a, b, c, d, x, s, t) { | |
return cmn(c ^ (b | (~d)), a, b, x, s, t); | |
} | |
function md51(s) { | |
var n = s.length, | |
state = [1732584193, -271733879, -1732584194, 271733878], i; | |
for (i=64; i<=s.length; i+=64) { | |
md5cycle(state, md5blk(s.substring(i-64, i))); | |
} | |
s = s.substring(i-64); | |
var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; | |
for (i=0; i<s.length; i++) | |
tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3); | |
tail[i>>2] |= 0x80 << ((i%4) << 3); | |
if (i > 55) { | |
md5cycle(state, tail); | |
for (i=0; i<16; i++) tail[i] = 0; | |
} | |
tail[14] = n*8; | |
md5cycle(state, tail); | |
return state; | |
} | |
window['md51'] = md51; | |
function md5blk(s) { | |
var md5blks = [], i; | |
for (i=0; i<64; i+=4) { | |
md5blks[i>>2] = s.charCodeAt(i) | |
+ (s.charCodeAt(i+1) << 8) | |
+ (s.charCodeAt(i+2) << 16) | |
+ (s.charCodeAt(i+3) << 24); | |
} | |
return md5blks; | |
} | |
var hex_chr = '0123456789abcdef'.split(''); | |
function rhex(n) | |
{ | |
var s='', j=0; | |
for(; j<4; j++) | |
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] | |
+ hex_chr[(n >> (j * 8)) & 0x0F]; | |
return s; | |
} | |
function hex(x) { | |
for (var i=0; i<x.length; i++) | |
x[i] = rhex(x[i]); | |
return x.join(''); | |
} | |
function md5(s) { | |
return hex(md51(s)); | |
} | |
function add32(a, b) { | |
return (a + b) & 0xFFFFFFFF; | |
} | |
// Functions for dealing with arrays. | |
function newArr(n, x) { | |
var arr = []; | |
for(; n >= 0; --n) { | |
arr.push(x); | |
} | |
return arr; | |
} | |
// Create all views at once; perhaps it's wasteful, but it's better than having | |
// to check for the right view at each read or write. | |
function newByteArr(n) { | |
// Pad the thing to multiples of 8. | |
var padding = 8 - n % 8; | |
if(padding < 8) { | |
n += padding; | |
} | |
var arr = {}; | |
var buffer = new ArrayBuffer(n); | |
var views = {}; | |
views['i8'] = new Int8Array(buffer); | |
views['i16'] = new Int16Array(buffer); | |
views['i32'] = new Int32Array(buffer); | |
views['w8'] = new Uint8Array(buffer); | |
views['w16'] = new Uint16Array(buffer); | |
views['w32'] = new Uint32Array(buffer); | |
views['f32'] = new Float32Array(buffer); | |
views['f64'] = new Float64Array(buffer); | |
arr['b'] = buffer; | |
arr['v'] = views; | |
// ByteArray and Addr are the same thing, so keep an offset if we get | |
// casted. | |
arr['off'] = 0; | |
return arr; | |
} | |
// An attempt at emulating pointers enough for ByteString and Text to be | |
// usable without patching the hell out of them. | |
// The general idea is that Addr# is a byte array with an associated offset. | |
function plusAddr(addr, off) { | |
var newaddr = {}; | |
newaddr['off'] = addr['off'] + off; | |
newaddr['b'] = addr['b']; | |
newaddr['v'] = addr['v']; | |
return newaddr; | |
} | |
function writeOffAddr(type, elemsize, addr, off, x) { | |
addr['v'][type][addr.off/elemsize + off] = x; | |
} | |
function readOffAddr(type, elemsize, addr, off) { | |
return addr['v'][type][addr.off/elemsize + off]; | |
} | |
// Two addresses are equal if they point to the same buffer and have the same | |
// offset. For other comparisons, just use the offsets - nobody in their right | |
// mind would check if one pointer is less than another, completely unrelated, | |
// pointer and then act on that information anyway. | |
function addrEq(a, b) { | |
if(a == b) { | |
return true; | |
} | |
return a && b && a['b'] == b['b'] && a['off'] == b['off']; | |
} | |
function addrLT(a, b) { | |
if(a) { | |
return b && a['off'] < b['off']; | |
} else { | |
return (b != 0); | |
} | |
} | |
function addrGT(a, b) { | |
if(b) { | |
return a && a['off'] > b['off']; | |
} else { | |
return (a != 0); | |
} | |
} | |
function withChar(f, charCode) { | |
return f(String.fromCharCode(charCode)).charCodeAt(0); | |
} | |
function u_towlower(charCode) { | |
return withChar(function(c) {return c.toLowerCase()}, charCode); | |
} | |
function u_towupper(charCode) { | |
return withChar(function(c) {return c.toUpperCase()}, charCode); | |
} | |
var u_towtitle = u_towupper; | |
function u_iswupper(charCode) { | |
var c = String.fromCharCode(charCode); | |
return c == c.toUpperCase() && c != c.toLowerCase(); | |
} | |
function u_iswlower(charCode) { | |
var c = String.fromCharCode(charCode); | |
return c == c.toLowerCase() && c != c.toUpperCase(); | |
} | |
function u_iswdigit(charCode) { | |
return charCode >= 48 && charCode <= 57; | |
} | |
function u_iswcntrl(charCode) { | |
return charCode <= 0x1f || charCode == 0x7f; | |
} | |
function u_iswspace(charCode) { | |
var c = String.fromCharCode(charCode); | |
return c.replace(/\s/g,'') != c; | |
} | |
function u_iswalpha(charCode) { | |
var c = String.fromCharCode(charCode); | |
return c.replace(__hs_alphare, '') != c; | |
} | |
function u_iswalnum(charCode) { | |
return u_iswdigit(charCode) || u_iswalpha(charCode); | |
} | |
function u_iswprint(charCode) { | |
return !u_iswcntrl(charCode); | |
} | |
function u_gencat(c) { | |
throw 'u_gencat is only supported with --full-unicode.'; | |
} | |
// Regex that matches any alphabetic character in any language. Horrible thing. | |
var __hs_alphare = /[\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/g; | |
// 2D Canvas drawing primitives. | |
function jsHasCtx2D(elem) {return !!elem.getContext;} | |
function jsGetCtx2D(elem) {return elem.getContext('2d');} | |
function jsBeginPath(ctx) {ctx.beginPath();} | |
function jsMoveTo(ctx, x, y) {ctx.moveTo(x, y);} | |
function jsLineTo(ctx, x, y) {ctx.lineTo(x, y);} | |
function jsStroke(ctx) {ctx.stroke();} | |
function jsFill(ctx) {ctx.fill();} | |
function jsRotate(ctx, radians) {ctx.rotate(radians);} | |
function jsTranslate(ctx, x, y) {ctx.translate(x, y);} | |
function jsScale(ctx, x, y) {ctx.scale(x, y);} | |
function jsPushState(ctx) {ctx.save();} | |
function jsPopState(ctx) {ctx.restore();} | |
function jsResetCanvas(el) {el.width = el.width;} | |
function jsDrawImage(ctx, img, x, y) {ctx.drawImage(img, x, y);} | |
function jsDrawImageClipped(ctx, img, x, y, cx, cy, cw, ch) { | |
ctx.drawImage(img, cx, cy, cw, ch, x, y, cw, ch); | |
} | |
function jsDrawText(ctx, str, x, y) {ctx.fillText(str, x, y);} | |
function jsClip(ctx) {ctx.clip();} | |
function jsArc(ctx, x, y, radius, fromAngle, toAngle) { | |
ctx.arc(x, y, radius, fromAngle, toAngle); | |
} | |
function jsCanvasToDataURL(el) {return el.toDataURL('image/png');} | |
// Simulate handles. | |
// When implementing new handles, remember that passed strings may be thunks, | |
// and so need to be evaluated before use. | |
function jsNewHandle(init, read, write, flush, close, seek, tell) { | |
var h = { | |
read: read || function() {}, | |
write: write || function() {}, | |
seek: seek || function() {}, | |
tell: tell || function() {}, | |
close: close || function() {}, | |
flush: flush || function() {} | |
}; | |
init.call(h); | |
return h; | |
} | |
function jsReadHandle(h, len) {return h.read(len);} | |
function jsWriteHandle(h, str) {return h.write(str);} | |
function jsFlushHandle(h) {return h.flush();} | |
function jsCloseHandle(h) {return h.close();} | |
function jsMkConWriter(op) { | |
return function(str) { | |
str = E(str); | |
var lines = (this.buf + str).split('\n'); | |
for(var i = 0; i < lines.length-1; ++i) { | |
op.call(console, lines[i]); | |
} | |
this.buf = lines[lines.length-1]; | |
} | |
} | |
function jsMkStdout() { | |
return jsNewHandle( | |
function() {this.buf = '';}, | |
function(_) {return '';}, | |
jsMkConWriter(console.log), | |
function() {console.log(this.buf); this.buf = '';} | |
); | |
} | |
function jsMkStderr() { | |
return jsNewHandle( | |
function() {this.buf = '';}, | |
function(_) {return '';}, | |
jsMkConWriter(console.warn), | |
function() {console.warn(this.buf); this.buf = '';} | |
); | |
} | |
function jsMkStdin() { | |
return jsNewHandle( | |
function() {this.buf = '';}, | |
function(len) { | |
while(this.buf.length < len) { | |
this.buf += prompt('[stdin]') + '\n'; | |
} | |
var ret = this.buf.substr(0, len); | |
this.buf = this.buf.substr(len); | |
return ret; | |
} | |
); | |
} | |
// "Weak Pointers". Mostly useless implementation since | |
// JS does its own GC. | |
function mkWeak(key, val, fin) { | |
fin = !fin? function() {}: fin; | |
return {key: key, val: val, fin: fin}; | |
} | |
function derefWeak(w) { | |
return [0, 1, E(w).val]; | |
} | |
function finalizeWeak(w) { | |
return [0, B(A(E(w).fin, [0]))]; | |
} | |
var _0=0,_1=function(_){var _2=jsLog("Hello World!");return _0;},_3=function(_){return new F(function(){return _1(_);});}; | |
var hasteMain = function() {B(A(_3, [0]));};window.onload = hasteMain; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment