haste-compiler 0.2.9 → 0.2.10
raw patch · 14 files changed
+980/−81 lines, 14 files
Files
- haste-compiler.cabal +2/−1
- lib/Int64.js +850/−0
- lib/Integer.js +52/−36
- lib/rts.js +7/−13
- lib/stdlib.js +10/−2
- src/Data/JSTarget/Optimize.hs +4/−7
- src/Data/JSTarget/Print.hs +2/−2
- src/Haste/Builtins.hs +1/−1
- src/Haste/CodeGen.hs +41/−14
- src/Haste/Config.hs +3/−2
- src/Haste/PrimOps.hs +4/−0
- src/Haste/Version.hs +1/−1
- src/haste-boot.hs +1/−1
- src/haste-inst.hs +2/−1
haste-compiler.cabal view
@@ -1,5 +1,5 @@ Name: haste-compiler-Version: 0.2.9+Version: 0.2.10 License: BSD3 License-File: LICENSE Synopsis: Haskell To ECMAScript compiler@@ -26,6 +26,7 @@ MVar.js StableName.js Integer.js+ Int64.js md5.js array.js pointers.js
+ lib/Int64.js view
@@ -0,0 +1,850 @@+// 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.++/**+ * Constructs a 64-bit two's-complement integer, given its low and high 32-bit+ * values as *signed* integers. See the from* functions below for more+ * convenient ways of constructing Longs.+ *+ * The internal representation of a long is the two given signed, 32-bit values.+ * We use 32-bit pieces because these are the size of integers on which+ * Javascript performs bit-operations. For operations like addition and+ * multiplication, we split each number into 16-bit pieces, which can easily be+ * multiplied within Javascript's floating-point representation without overflow+ * or change in sign.+ *+ * In the algorithms below, we frequently reduce the negative case to the+ * positive case by negating the input(s) and then post-processing the result.+ * Note that we must ALWAYS check specially whether those values are MIN_VALUE+ * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as+ * a positive number, it overflows back into a negative). Not handling this+ * case would often result in infinite recursion.+ *+ * @param {number} low The low (signed) 32 bits of the long.+ * @param {number} high The high (signed) 32 bits of the long.+ * @constructor+ */+Long = function(low, high) {+ /**+ * @type {number}+ * @private+ */+ this.low_ = low | 0; // force into 32 signed bits.++ /**+ * @type {number}+ * @private+ */+ this.high_ = high | 0; // force into 32 signed bits.+};+++// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the+// from* methods on which they depend.+++/**+ * A cache of the Long representations of small integer values.+ * @type {!Object}+ * @private+ */+Long.IntCache_ = {};+++/**+ * Returns a Long representing the given (32-bit) integer value.+ * @param {number} value The 32-bit integer in question.+ * @return {!Long} The corresponding Long value.+ */+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;+};+++/**+ * Returns a Long representing the given value, provided that it is a finite+ * number. Otherwise, zero is returned.+ * @param {number} value The number in question.+ * @return {!Long} The corresponding Long value.+ */+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);+ }+};+++/**+ * Returns a Long representing the 64-bit integer that comes by concatenating+ * the given high and low bits. Each is assumed to use 32 bits.+ * @param {number} lowBits The low 32-bits.+ * @param {number} highBits The high 32-bits.+ * @return {!Long} The corresponding Long value.+ */+Long.fromBits = function(lowBits, highBits) {+ return new Long(lowBits, highBits);+};+++/**+ * Returns a Long representation of the given string, written using the given+ * radix.+ * @param {string} str The textual representation of the Long.+ * @param {number=} opt_radix The radix in which the text is written.+ * @return {!Long} The corresponding Long value.+ */+Long.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 Long.fromString(str.substring(1), radix).negate();+ } else if (str.indexOf('-') >= 0) {+ throw Error('number format error: interior "-" character: ' + str);+ }++ // Do several (8) digits each time through the loop, so as to+ // minimize the calls to the very expensive emulated div.+ var radixToPower = Long.fromNumber(Math.pow(radix, 8));++ var result = Long.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 = Long.fromNumber(Math.pow(radix, size));+ result = result.multiply(power).add(Long.fromNumber(value));+ } else {+ result = result.multiply(radixToPower);+ result = result.add(Long.fromNumber(value));+ }+ }+ return result;+};+++// NOTE: the compiler should inline these constant values below and then remove+// these variables, so there should be no runtime penalty for these.+++/**+ * Number used repeated below in calculations. This must appear before the+ * first call to any from* function below.+ * @type {number}+ * @private+ */+Long.TWO_PWR_16_DBL_ = 1 << 16;+++/**+ * @type {number}+ * @private+ */+Long.TWO_PWR_24_DBL_ = 1 << 24;+++/**+ * @type {number}+ * @private+ */+Long.TWO_PWR_32_DBL_ =+ Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_;+++/**+ * @type {number}+ * @private+ */+Long.TWO_PWR_31_DBL_ =+ Long.TWO_PWR_32_DBL_ / 2;+++/**+ * @type {number}+ * @private+ */+Long.TWO_PWR_48_DBL_ =+ Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_;+++/**+ * @type {number}+ * @private+ */+Long.TWO_PWR_64_DBL_ =+ Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_;+++/**+ * @type {number}+ * @private+ */+Long.TWO_PWR_63_DBL_ =+ Long.TWO_PWR_64_DBL_ / 2;+++/** @type {!Long} */+Long.ZERO = Long.fromInt(0);+++/** @type {!Long} */+Long.ONE = Long.fromInt(1);+++/** @type {!Long} */+Long.NEG_ONE = Long.fromInt(-1);+++/** @type {!Long} */+Long.MAX_VALUE =+ Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);+++/** @type {!Long} */+Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0);+++/**+ * @type {!Long}+ * @private+ */+Long.TWO_PWR_24_ = Long.fromInt(1 << 24);+++/** @return {number} The value, assuming it is a 32-bit integer. */+Long.prototype.toInt = function() {+ return this.low_;+};+++/** @return {number} The closest floating-point representation to this value. */+Long.prototype.toNumber = function() {+ return this.high_ * Long.TWO_PWR_32_DBL_ ++ this.getLowBitsUnsigned();+};+++/**+ * @param {number=} opt_radix The radix in which the text should be written.+ * @return {string} The textual representation of this value.+ * @override+ */+Long.prototype.toString = function(opt_radix) {+ var radix = opt_radix || 10;+ if (radix < 2 || 36 < radix) {+ throw Error('radix out of range: ' + radix);+ }++ if (this.isZero()) {+ return '0';+ }++ if (this.isNegative()) {+ if (this.equals(Long.MIN_VALUE)) {+ // We need to change the Long value before it can be negated, so we remove+ // the bottom-most digit in this base and then recurse to do the rest.+ var radixLong = Long.fromNumber(radix);+ var div = this.div(radixLong);+ var rem = div.multiply(radixLong).subtract(this);+ return div.toString(radix) + rem.toInt().toString(radix);+ } else {+ return '-' + this.negate().toString(radix);+ }+ }++ // Do several (6) digits each time through the loop, so as to+ // minimize the calls to the very expensive emulated div.+ var radixToPower = Long.fromNumber(Math.pow(radix, 6));++ var rem = this;+ var result = '';+ while (true) {+ var remDiv = rem.div(radixToPower);+ var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();+ var digits = intval.toString(radix);++ rem = remDiv;+ if (rem.isZero()) {+ return digits + result;+ } else {+ while (digits.length < 6) {+ digits = '0' + digits;+ }+ result = '' + digits + result;+ }+ }+};+++/** @return {number} The high 32-bits as a signed value. */+Long.prototype.getHighBits = function() {+ return this.high_;+};+++/** @return {number} The low 32-bits as a signed value. */+Long.prototype.getLowBits = function() {+ return this.low_;+};+++/** @return {number} The low 32-bits as an unsigned value. */+Long.prototype.getLowBitsUnsigned = function() {+ return (this.low_ >= 0) ?+ this.low_ : Long.TWO_PWR_32_DBL_ + this.low_;+};+++/**+ * @return {number} Returns the number of bits needed to represent the absolute+ * value of this Long.+ */+Long.prototype.getNumBitsAbs = function() {+ if (this.isNegative()) {+ if (this.equals(Long.MIN_VALUE)) {+ return 64;+ } else {+ return this.negate().getNumBitsAbs();+ }+ } else {+ var val = this.high_ != 0 ? this.high_ : this.low_;+ for (var bit = 31; bit > 0; bit--) {+ if ((val & (1 << bit)) != 0) {+ break;+ }+ }+ return this.high_ != 0 ? bit + 33 : bit + 1;+ }+};+++/** @return {boolean} Whether this value is zero. */+Long.prototype.isZero = function() {+ return this.high_ == 0 && this.low_ == 0;+};+++/** @return {boolean} Whether this value is negative. */+Long.prototype.isNegative = function() {+ return this.high_ < 0;+};+++/** @return {boolean} Whether this value is odd. */+Long.prototype.isOdd = function() {+ return (this.low_ & 1) == 1;+};+++/**+ * @param {Long} other Long to compare against.+ * @return {boolean} Whether this Long equals the other.+ */+Long.prototype.equals = function(other) {+ return (this.high_ == other.high_) && (this.low_ == other.low_);+};+++/**+ * @param {Long} other Long to compare against.+ * @return {boolean} Whether this Long does not equal the other.+ */+Long.prototype.notEquals = function(other) {+ return (this.high_ != other.high_) || (this.low_ != other.low_);+};+++/**+ * @param {Long} other Long to compare against.+ * @return {boolean} Whether this Long is less than the other.+ */+Long.prototype.lessThan = function(other) {+ return this.compare(other) < 0;+};+++/**+ * @param {Long} other Long to compare against.+ * @return {boolean} Whether this Long is less than or equal to the other.+ */+Long.prototype.lessThanOrEqual = function(other) {+ return this.compare(other) <= 0;+};+++/**+ * @param {Long} other Long to compare against.+ * @return {boolean} Whether this Long is greater than the other.+ */+Long.prototype.greaterThan = function(other) {+ return this.compare(other) > 0;+};+++/**+ * @param {Long} other Long to compare against.+ * @return {boolean} Whether this Long is greater than or equal to the other.+ */+Long.prototype.greaterThanOrEqual = function(other) {+ return this.compare(other) >= 0;+};+++/**+ * Compares this Long with the given one.+ * @param {Long} other Long to compare against.+ * @return {number} 0 if they are the same, 1 if the this is greater, and -1+ * if the given one is greater.+ */+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;+ }++ // at this point, the signs are the same, so subtraction will not overflow+ if (this.subtract(other).isNegative()) {+ return -1;+ } else {+ return 1;+ }+};+++/** @return {!Long} The negation of this value. */+Long.prototype.negate = function() {+ if (this.equals(Long.MIN_VALUE)) {+ return Long.MIN_VALUE;+ } else {+ return this.not().add(Long.ONE);+ }+};+++/**+ * Returns the sum of this and the given Long.+ * @param {Long} other Long to add to this one.+ * @return {!Long} The sum of this and the given Long.+ */+Long.prototype.add = function(other) {+ // Divide each number into 4 chunks of 16 bits, and then sum the chunks.++ 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);+};+++/**+ * Returns the difference of this and the given Long.+ * @param {Long} other Long to subtract from this.+ * @return {!Long} The difference of this and the given Long.+ */+Long.prototype.subtract = function(other) {+ return this.add(other.negate());+};+++/**+ * Returns the product of this and the given long.+ * @param {Long} other Long to multiply with this.+ * @return {!Long} The product of this and the other.+ */+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 both longs are small, use float multiplication+ if (this.lessThan(Long.TWO_PWR_24_) &&+ other.lessThan(Long.TWO_PWR_24_)) {+ return Long.fromNumber(this.toNumber() * other.toNumber());+ }++ // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.+ // We can skip products that would overflow.++ 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);+};+++/**+ * Returns this Long divided by the given one.+ * @param {Long} other Long by which to divide.+ * @return {!Long} This Long divided by the given one.+ */+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; // recall that -MIN_VALUE == MIN_VALUE+ } else if (other.equals(Long.MIN_VALUE)) {+ return Long.ONE;+ } else {+ // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.+ 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();+ }++ // Repeat the following until the remainder is less than other: find a+ // floating-point that approximates remainder / other *from below*, add this+ // into the result, and subtract it from the remainder. It is critical that+ // the approximate value is less than or equal to the real value so that the+ // remainder never becomes negative.+ var res = Long.ZERO;+ var rem = this;+ while (rem.greaterThanOrEqual(other)) {+ // Approximate the result of division. This may be a little greater or+ // smaller than the actual value.+ var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));++ // We will tweak the approximate result by changing it in the 48-th digit or+ // the smallest non-fractional digit, whichever is larger.+ var log2 = Math.ceil(Math.log(approx) / Math.LN2);+ var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);++ // Decrease the approximation until it is smaller than the remainder. Note+ // that if it is too large, the product overflows and is negative.+ 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);+ }++ // We know the answer can't be zero... and actually, zero would cause+ // infinite recursion since we would make no progress.+ if (approxRes.isZero()) {+ approxRes = Long.ONE;+ }++ res = res.add(approxRes);+ rem = rem.subtract(approxRem);+ }+ return res;+};+++/**+ * Returns this Long modulo the given one.+ * @param {Long} other Long by which to mod.+ * @return {!Long} This Long modulo the given one.+ */+Long.prototype.modulo = function(other) {+ return this.subtract(this.div(other).multiply(other));+};+++/** @return {!Long} The bitwise-NOT of this value. */+Long.prototype.not = function() {+ return Long.fromBits(~this.low_, ~this.high_);+};+++/**+ * Returns the bitwise-AND of this Long and the given one.+ * @param {Long} other The Long with which to AND.+ * @return {!Long} The bitwise-AND of this and the other.+ */+Long.prototype.and = function(other) {+ return Long.fromBits(this.low_ & other.low_,+ this.high_ & other.high_);+};+++/**+ * Returns the bitwise-OR of this Long and the given one.+ * @param {Long} other The Long with which to OR.+ * @return {!Long} The bitwise-OR of this and the other.+ */+Long.prototype.or = function(other) {+ return Long.fromBits(this.low_ | other.low_,+ this.high_ | other.high_);+};+++/**+ * Returns the bitwise-XOR of this Long and the given one.+ * @param {Long} other The Long with which to XOR.+ * @return {!Long} The bitwise-XOR of this and the other.+ */+Long.prototype.xor = function(other) {+ return Long.fromBits(this.low_ ^ other.low_,+ this.high_ ^ other.high_);+};+++/**+ * Returns this Long with bits shifted to the left by the given amount.+ * @param {number} numBits The number of bits by which to shift.+ * @return {!Long} This shifted to the left by the given amount.+ */+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));+ }+ }+};+++/**+ * Returns this Long with bits shifted to the right by the given amount.+ * @param {number} numBits The number of bits by which to shift.+ * @return {!Long} This shifted to the right by the given amount.+ */+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);+ }+ }+};+++/**+ * Returns this Long with bits shifted to the right by the given amount, with+ * the new top bits matching the current sign bit.+ * @param {number} numBits The number of bits by which to shift.+ * @return {!Long} This shifted to the right by the given amount, with+ * zeros placed into the new leading bits.+ */+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);+ }+ }+};++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) {x.shiftLeft(bits);}+function hs_uncheckedIShiftRA64(x, bits) {x.shiftRight(bits);}+function hs_uncheckedIShiftRL64(x, bits) {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));+}
lib/Integer.js view
@@ -45,7 +45,7 @@ } }; -Integer.fromBits = function(bits) {+I_fromBits = function(bits) { var high = bits[bits.length - 1]; return new Integer(bits, high & (1 << 31) ? -1 : 0); };@@ -104,14 +104,14 @@ var val = 0; var pow = 1; for (var i = 0; i < self.bits_.length; i++) {- val += getBitsUnsigned(self, i) * pow;+ val += I_getBitsUnsigned(self, i) * pow; pow *= Integer.TWO_PWR_32_DBL_; } return val; } }; -var getBits = function(self, index) {+var I_getBits = function(self, index) { if (index < 0) { return 0; } else if (index < self.bits_.length) {@@ -121,8 +121,8 @@ } }; -var getBitsUnsigned = function(self, index) {- var val = getBits(self, index);+var I_getBitsUnsigned = function(self, index) {+ var val = I_getBits(self, index); return val >= 0 ? val : Integer.TWO_PWR_32_DBL_ + val; }; @@ -157,7 +157,7 @@ } var len = Math.max(self.bits_.length, other.bits_.length); for (var i = 0; i < len; i++) {- if (getBits(self, i) != getBits(other, i)) {+ if (I_getBits(self, i) != I_getBits(other, i)) { return false; } }@@ -168,19 +168,19 @@ return !I_equals(self, other); }; -var greaterThan = function(self, other) {+var I_greaterThan = function(self, other) { return I_compare(self, other) > 0; }; -var greaterThanOrEqual = function(self, other) {+var I_greaterThanOrEqual = function(self, other) { return I_compare(self, other) >= 0; }; -var lessThan = function(self, other) {+var I_lessThan = function(self, other) { return I_compare(self, other) < 0; }; -var lessThanOrEqual = function(self, other) {+var I_lessThanOrEqual = function(self, other) { return I_compare(self, other) <= 0; }; @@ -204,10 +204,10 @@ var bit_index = (numBits - 1) % 32; var bits = []; for (var i = 0; i < arr_index; i++) {- bits[i] = getBits(self, i);+ bits[i] = I_getBits(self, i); } var sigBits = bit_index == 31 ? 0xFFFFFFFF : (1 << (bit_index + 1)) - 1;- var val = getBits(self, arr_index) & sigBits;+ var val = I_getBits(self, arr_index) & sigBits; if (val & (1 << bit_index)) { val |= 0xFFFFFFFF - sigBits; bits[arr_index] = val;@@ -228,11 +228,11 @@ var carry = 0; for (var i = 0; i <= len; i++) {- var a1 = getBits(self, i) >>> 16;- var a0 = getBits(self, i) & 0xFFFF;+ var a1 = I_getBits(self, i) >>> 16;+ var a0 = I_getBits(self, i) & 0xFFFF; - var b1 = getBits(other, i) >>> 16;- var b0 = getBits(other, 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;@@ -241,7 +241,7 @@ c1 &= 0xFFFF; arr[i] = (c1 << 16) | c0; }- return Integer.fromBits(arr);+ return I_fromBits(arr); }; var I_sub = function(self, other) {@@ -265,8 +265,8 @@ return I_negate(I_mul(self, I_negate(other))); } - if (lessThan(self, Integer.TWO_PWR_24_) &&- lessThan(other, Integer.TWO_PWR_24_)) {+ if (I_lessThan(self, Integer.TWO_PWR_24_) &&+ I_lessThan(other, Integer.TWO_PWR_24_)) { return I_fromNumber(I_toNumber(self) * I_toNumber(other)); } @@ -277,11 +277,11 @@ } for (var i = 0; i < self.bits_.length; i++) { for (var j = 0; j < other.bits_.length; j++) {- var a1 = getBits(self, i) >>> 16;- var a0 = getBits(self, i) & 0xFFFF;+ var a1 = I_getBits(self, i) >>> 16;+ var a0 = I_getBits(self, i) & 0xFFFF; - var b1 = getBits(other, j) >>> 16;- var b0 = getBits(other, j) & 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);@@ -315,7 +315,7 @@ } var I_div = function(self, other) {- if(greaterThan(self, Integer.ZERO) != greaterThan(other, Integer.ZERO)) {+ 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); }@@ -350,13 +350,13 @@ var res = Integer.ZERO; var rem = self;- while (greaterThanOrEqual(rem, other)) {+ 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) || greaterThan(approxRem, rem)) {+ while (isNegative(approxRem) || I_greaterThan(approxRem, rem)) { approx -= delta; approxRes = I_fromNumber(approx); approxRem = I_mul(approxRes, other);@@ -389,7 +389,7 @@ var len = Math.max(self.bits_.length, other.bits_.length); var arr = []; for (var i = 0; i < len; i++) {- arr[i] = getBits(self, i) & getBits(other, i);+ arr[i] = I_getBits(self, i) & I_getBits(other, i); } return new Integer(arr, self.sign_ & other.sign_); };@@ -398,7 +398,7 @@ var len = Math.max(self.bits_.length, other.bits_.length); var arr = []; for (var i = 0; i < len; i++) {- arr[i] = getBits(self, i) | getBits(other, i);+ arr[i] = I_getBits(self, i) | I_getBits(other, i); } return new Integer(arr, self.sign_ | other.sign_); };@@ -407,7 +407,7 @@ var len = Math.max(self.bits_.length, other.bits_.length); var arr = []; for (var i = 0; i < len; i++) {- arr[i] = getBits(self, i) ^ getBits(other, i);+ arr[i] = I_getBits(self, i) ^ I_getBits(other, i); } return new Integer(arr, self.sign_ ^ other.sign_); };@@ -419,10 +419,10 @@ var arr = []; for (var i = 0; i < len; i++) { if (bit_delta > 0) {- arr[i] = (getBits(self, i - arr_delta) << bit_delta) |- (getBits(self, i - arr_delta - 1) >>> (32 - bit_delta));+ arr[i] = (I_getBits(self, i - arr_delta) << bit_delta) |+ (I_getBits(self, i - arr_delta - 1) >>> (32 - bit_delta)); } else {- arr[i] = getBits(self, i - arr_delta);+ arr[i] = I_getBits(self, i - arr_delta); } } return new Integer(arr, self.sign_);@@ -435,10 +435,10 @@ var arr = []; for (var i = 0; i < len; i++) { if (bit_delta > 0) {- arr[i] = (getBits(self, i + arr_delta) >>> bit_delta) |- (getBits(self, i + arr_delta + 1) << (32 - bit_delta));+ arr[i] = (I_getBits(self, i + arr_delta) >>> bit_delta) |+ (I_getBits(self, i + arr_delta + 1) << (32 - bit_delta)); } else {- arr[i] = getBits(self, i + arr_delta);+ arr[i] = I_getBits(self, i + arr_delta); } } return new Integer(arr, self.sign_);@@ -464,7 +464,7 @@ var I_decodeDouble = function(x) { var dec = decodeDouble(x);- var mantissa = Integer.fromBits([dec[3], dec[2]]);+ var mantissa = I_fromBits([dec[3], dec[2]]); if(dec[1] < 0) { mantissa = I_negate(mantissa); }@@ -503,4 +503,20 @@ 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); }
lib/rts.js view
@@ -253,19 +253,6 @@ } } -function hs_eqWord64(a, b) {- return (a[0] == b[0] && a[1] == b[1]);-}--// Word64# representation: (Word, Word)-function hs_wordToWord64(low) {- return [0, low];-}--function hs_mkWord64(high, low) {- return [high, low];-}- var coercionToken = undefined; /* Haste represents constructors internally using 1 for the first constructor,@@ -286,6 +273,13 @@ var __word_encodeFloat = __word_encodeDouble; var jsRound = Math.round; // Stupid GHC doesn't like periods in FFI IDs...+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; }
lib/stdlib.js view
@@ -124,6 +124,14 @@ elem[prop] = val; } +function jsGetAttr(elem, prop) {+ return elem.getAttribute(prop).toString();+}++function jsSetAttr(elem, prop, val) {+ elem.setAttribute(prop, val);+}+ function jsGetStyle(elem, prop) { return elem.style[prop].toString(); }@@ -223,7 +231,7 @@ // Escape all double quotes in a string function jsUnquote(str) {- return str.replace(/"/, '\\"');+ return str.replace(/"/g, '\\"'); } // Parse a JSON message into a Haste.JSON.JSON value.@@ -267,7 +275,7 @@ ks.unshift(k); } var xs = [0];- for(var i in ks) {+ for(var i = 0; i < ks.length; i++) { xs = [1, [0, [0,ks[i]], toHS(obj[ks[i]])], xs]; } return [4, xs];
src/Data/JSTarget/Optimize.hs view
@@ -17,7 +17,7 @@ optimizeFun f (AST ast js) = flip runTravM js $ do shrinkCase ast- >>= inlineAssigns True+ >>= inlineAssigns >>= optimizeArrays >>= inlineReturns >>= zapJSStringConversions@@ -29,7 +29,7 @@ topLevelInline :: AST Stm -> AST Stm topLevelInline (AST ast js) = flip runTravM js $ do- inlineAssigns False ast+ inlineAssigns ast >>= optimizeArrays >>= optimizeThunks >>= optimizeArrays@@ -97,8 +97,8 @@ -- care about the assignment side effect. -- -- TODO: don't inline thunks into functions!-inlineAssigns :: JSTrav ast => Bool -> ast -> TravM ast-inlineAssigns blackholeOK ast = do+inlineAssigns :: JSTrav ast => ast -> TravM ast+inlineAssigns ast = do inlinable <- gatherInlinable ast mapJS (const True) return (inl inlinable) ast where@@ -112,9 +112,6 @@ case M.lookup lhs m of Just occ | occ == occursLocal -> case occ of- -- Never-used symbols don't need assignment.- Never | blackholeOK -> do- return (Assign blackHole ex next) -- Inline of any non-lambda value Once | mayReorder -> do replaceEx (not <$> isShared) (Var lhs) ex next
src/Data/JSTarget/Print.hs view
@@ -213,8 +213,8 @@ opParens Add a (Lit (LNum (-n))) opParens Sub (Lit (LNum 0)) b = case b of- BinOp _ _ _ -> "-(" .+. pp b .+. ")"- _ -> "-" .+. pp b+ BinOp _ _ _ -> " -(" .+. pp b .+. ")"+ _ -> " -" .+. pp b opParens op a b = do let bparens = case b of Lit (LNum n) | n < 0 -> \x -> "(".+. pp x .+. ")"
src/Haste/Builtins.hs view
@@ -10,7 +10,7 @@ (Just "GHC.Prim", "coercionToken#") -> Just $ foreignVar "coercionToken" (Just "GHC.Prim", "realWorld#") ->- Just $ foreignVar "realWorld"+ Just $ foreignVar "_" (Just "GHC.Err", "error") -> Just $ foreignVar "err"
src/Haste/CodeGen.hs view
@@ -4,6 +4,7 @@ import Control.Applicative import Control.Monad import Data.Int+import Data.Bits import Data.Word import Data.Char import Data.List (partition, foldl')@@ -29,7 +30,7 @@ import TyCon import BasicTypes -- AST stuff-import Data.JSTarget as J+import Data.JSTarget as J hiding ((.&.)) import Data.JSTarget.AST (Exp (..), Stm (..), LHS (..)) -- General Haste stuff import Haste.Config@@ -108,13 +109,26 @@ genEx (StgLit l) = do genLit l genEx (StgConApp con args) = do- (tag, stricts) <- genDataCon con- (args', stricts') <- genArgsPair $ zip args stricts- -- Don't create unboxed tuples with a single element.- case (isUnboxedTupleCon con, args') of- (True, [arg]) -> return $ evaluate arg (head stricts')- _ -> mkCon tag args' stricts'+ -- On 64 bit machines, GHC constructs small integers from Ints rather than+ -- Int64, so we need to deal with it or be unable to reliably create Int64+ -- or Integer values.+ case (dataConNameModule con, args) of+ (("S#", "GHC.Integer.Type"), [StgLitArg (MachInt n)]) | tooLarge n -> do+ return $ mkInteger n+ _ -> do+ (tag, stricts) <- genDataCon con+ (args', stricts') <- genArgsPair $ zip args stricts+ -- Don't create unboxed tuples with a single element.+ case (isUnboxedTupleCon con, args') of+ (True, [arg]) -> return $ evaluate arg (head stricts')+ _ -> mkCon tag args' stricts' where+ mkInteger n =+ array [litN 1, callForeign "I_fromBits" [array [lit lo, lit hi]]]+ where+ lo = n .&. 0xffffffff+ hi = n `shiftR` 32+ tooLarge n = n > 2147483647 || n < -2147483648 -- Always inline bools mkCon l _ _ | isEnumerationDataCon con = return l mkCon tag as ss = return $ array (tag : zipWith evaluate as ss)@@ -424,15 +438,20 @@ -- IMPORTANT: remember to update the RTS if any changes are made to the -- constructor tag values! genDataConTag :: DataCon -> AST Exp-genDataConTag d = do- let n = occNameString $ nameOccName $ dataConName d- m = moduleNameString $ moduleName $ nameModule $ dataConName d- case (n, m) of+genDataConTag d =+ case dataConNameModule d of ("True", "GHC.Types") -> lit True ("False", "GHC.Types") -> lit False _ -> lit (fromIntegral (dataConTag d - fIRST_TAG) :: Double) +-- | Get the name and module of the given data constructor.+dataConNameModule :: DataCon -> (String, String)+dataConNameModule d =+ (occNameString $ nameOccName $ dataConName d,+ moduleNameString $ moduleName $ nameModule $ dataConName d)++ -- | Generate literals. genLit :: L.Literal -> JSGen Config (AST Exp) genLit l = do@@ -450,16 +469,24 @@ | w > 0xffffffff -> do warn Verbose (constFail "Word" w) return $ truncWord w | otherwise -> return . litN $ fromIntegral w- MachWord64 w -> return . litN $ fromIntegral w+ MachWord64 w -> return $ word64 w MachNullAddr -> return $ litN 0- MachInt64 n -> return . litN $ fromIntegral n- LitInteger n _ -> return . lit $ n+ MachInt64 n -> return $ int64 n+ LitInteger n _ -> return $ lit n MachLabel _ _ _ -> return $ lit ":(" -- Labels point to machine code - ignore! where constFail t n = t ++ " literal " ++ show n ++ " doesn't fit in 32 bits;" ++ " truncating!" truncInt n = litN . fromIntegral $ (fromIntegral n :: Int32) truncWord w = litN . fromIntegral $ (fromIntegral w :: Word32)+ int64 n = callForeign "new Long" [lit lo, lit hi]+ where+ lo = n .&. 0xffffffff+ hi = n `shiftR` 32+ word64 n = callForeign "I_fromBits" [array [lit lo, lit hi]]+ where+ lo = n .&. 0xffffffff+ hi = n `shiftR` 32 -- | Generate a function application. genApp :: Var.Var -> [StgArg] -> JSGen Config (AST Exp)
src/Haste/Config.hs view
@@ -13,8 +13,9 @@ stdJSLibs :: [FilePath] stdJSLibs = map (jsDir </>) [- "rts.js", "stdlib.js", "MVar.js", "StableName.js", "Integer.js", "md5.js",- "array.js", "pointers.js", "cheap-unicode.js", "Canvas.js", "Handle.js"+ "rts.js", "stdlib.js", "MVar.js", "StableName.js", "Integer.js", "Int64.js",+ "md5.js", "array.js", "pointers.js", "cheap-unicode.js", "Canvas.js",+ "Handle.js" ] debugLib :: FilePath
src/Haste/PrimOps.hs view
@@ -298,6 +298,10 @@ MaskStatus -> Right $ litN 0 -- Misc. ops+ PopCntOp -> Right $ callForeign "popCnt" [head xs]+ PopCnt8Op -> Right $ callForeign "popCnt" [head xs]+ PopCnt16Op -> Right $ callForeign "popCnt" [head xs]+ PopCnt32Op -> Right $ callForeign "popCnt" [head xs] DelayOp -> Right $ defState SeqOp -> Right $ callForeign "E" [head xs] AtomicallyOp -> Right $ callSaturated (xs !! 0) []
src/Haste/Version.hs view
@@ -10,7 +10,7 @@ import Haste.Environment (hasteDir) hasteVersion :: Version-hasteVersion = Version [0, 2, 9] []+hasteVersion = Version [0, 2, 10] [] ghcVersion :: String ghcVersion = cProjectVersion
src/haste-boot.hs view
@@ -111,7 +111,7 @@ putStrLn "Couldn't unpack Closure compiler; continuing without." where closureURI =- "http://closure-compiler.googlecode.com/files/compiler-latest.zip"+ "http://dl.google.com/closure-compiler/compiler-latest.zip" -- | Build haste's base libs. buildLibs :: IO ()
src/haste-inst.hs view
@@ -19,7 +19,8 @@ "--with-hc-pkg=" ++ hastePkgBinary, "--with-hsc2hs=hsc2hs", "--prefix=" ++ hasteInstDir,- "--package-db=" ++ pkgDir]+ "--package-db=" ++ pkgDir,+ "-fhaste-inst"] main :: IO () main = do