txInteger fxToInteger(txMachine* the, txSlot* theSlot) { #if mxOptimize if (XS_INTEGER_KIND == theSlot->kind) return theSlot->value.integer; // this is the case over 90% of the time, so avoid the switch #endif again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_INTEGER_KIND; theSlot->value.integer = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_INTEGER_KIND; if (theSlot->value.boolean == 0) theSlot->value.integer = 0; else theSlot->value.integer = 1; break; case XS_INTEGER_KIND: break; case XS_NUMBER_KIND: theSlot->kind = XS_INTEGER_KIND; switch (c_fpclassify(theSlot->value.number)) { case C_FP_INFINITE: case C_FP_NAN: case C_FP_ZERO: theSlot->value.integer = 0; break; default: { #define MODULO 4294967296.0 txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO); if (aNumber >= MODULO / 2) aNumber -= MODULO; else if (aNumber < -MODULO / 2) aNumber += MODULO; theSlot->value.integer = (txInteger)aNumber; } break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); goto again; case XS_SYMBOL_KIND: mxTypeError("Cannot coerce symbol to integer"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: mxTypeError("Cannot coerce to integer"); break; } return theSlot->value.integer; }
void fx_Number_prototype_toString(txMachine* the) { char buffer[256]; txInteger radix; txSlot* slot = fxCheckNumber(the, mxThis); if (!slot) mxTypeError("this is no number"); if (mxArgc > 0) { radix = fxToInteger(the, mxArgv(0)); if (radix) { if ((radix < 2) || (36 < radix)) mxRangeError("invalid radix"); } else radix = 10; } else radix = 10; mxResult->kind = slot->kind; mxResult->value = slot->value; if (radix == 10) fxToString(the, mxResult); else { static char gxDigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; txString string = buffer + sizeof(buffer); txNumber value; txBoolean minus; value = mxResult->value.number; switch (c_fpclassify(value)) { case C_FP_INFINITE: if (value < 0) fxCopyStringC(the, mxResult, "-Infinity"); else fxCopyStringC(the, mxResult, "Infinity"); break; case C_FP_NAN: fxCopyStringC(the, mxResult, "NaN"); break; case C_FP_ZERO: fxCopyStringC(the, mxResult, "0"); break; default: *(--string) = 0; if (value < 0) { minus = 1; value = -value; } else minus = 0; do { *(--string) = gxDigits[(txInteger)c_fmod(value, radix)]; value = value / radix; } while (value >= 1); if (minus) *(--string) = '-'; fxCopyStringC(the, mxResult, string); } } }
void fx_isNaN(txMachine* the) { int fpclass; txNumber number = (mxArgc < 1) ? C_NAN : fxToNumber(the, mxArgv(0)); mxResult->kind = XS_BOOLEAN_KIND; mxResult->value.boolean = 0; fpclass = c_fpclassify(number); if (fpclass == FP_NAN) mxResult->value.boolean = 1; }
void fxSerializeJSONNumber(txMachine* the, txJSONSerializer* theSerializer, txNumber theNumber) { int fpclass = c_fpclassify(theNumber); if ((fpclass != FP_NAN) && (fpclass != FP_INFINITE)) { char aBuffer[256]; fxNumberToString(the, theNumber, aBuffer, sizeof(aBuffer), 0, 0); fxSerializeJSONChars(the, theSerializer, aBuffer); } else fxSerializeJSONChars(the, theSerializer, "null"); }
void fx_Number_isNaN(txMachine* the) { int fpclass; txSlot* slot = (mxArgc < 1) ? C_NULL : fxCheckNumber(the, mxArgv(0)); mxResult->kind = XS_BOOLEAN_KIND; mxResult->value.boolean = 0; if (slot) { fpclass = c_fpclassify(slot->value.number); if (fpclass == FP_NAN) mxResult->value.boolean = 1; } }
void fx_Number_isInteger(txMachine* the) { int fpclass; txSlot* slot = (mxArgc < 1) ? C_NULL : fxCheckNumber(the, mxArgv(0)); mxResult->kind = XS_BOOLEAN_KIND; mxResult->value.boolean = 0; if (slot) { fpclass = c_fpclassify(slot->value.number); if ((fpclass != FP_NAN) && (fpclass != FP_INFINITE)) { txNumber check = c_trunc(slot->value.number); if (slot->value.number == check) mxResult->value.boolean = 1; } } }
txBoolean fxToBoolean(txMachine* the, txSlot* theSlot) { switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_BOOLEAN_KIND; theSlot->value.boolean = 0; break; case XS_BOOLEAN_KIND: break; case XS_INTEGER_KIND: theSlot->kind = XS_BOOLEAN_KIND; theSlot->value.boolean = (theSlot->value.integer == 0) ? 0 : 1; break; case XS_NUMBER_KIND: theSlot->kind = XS_BOOLEAN_KIND; switch (c_fpclassify(theSlot->value.number)) { case FP_NAN: case FP_ZERO: theSlot->value.boolean = 0; break; default: theSlot->value.boolean = 1; break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_BOOLEAN_KIND; if (c_strlen(theSlot->value.string) == 0) theSlot->value.boolean = 0; else theSlot->value.boolean = 1; break; case XS_SYMBOL_KIND: case XS_REFERENCE_KIND: theSlot->kind = XS_BOOLEAN_KIND; theSlot->value.boolean = 1; break; default: mxTypeError("Cannot coerce to boolean"); break; } return theSlot->value.boolean; }
void fx_Date_prototype_setTime(txMachine* the) { txSlot* slot = fxCheckDate(the, mxThis); if (!slot) mxTypeError("this is no date"); if (mxArgc < 1) slot->value.number = C_NAN; else { txNumber number = fxToNumber(the, mxArgv(0)); int fpclass = c_fpclassify(number); if (fpclass != FP_NAN) { if (c_fabs(number) > 8.64e15) number = C_NAN; else number = c_trunc(number); } slot->value.number = number; } mxResult->value.number = slot->value.number; mxResult->kind = XS_NUMBER_KIND; }
txBoolean fxRunTest(txMachine* the) { txBoolean result; switch (the->stack->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: result = 0; break; case XS_BOOLEAN_KIND: result = the->stack->value.boolean; break; case XS_INTEGER_KIND: result = (the->stack->value.integer == 0) ? 0 : 1; break; case XS_NUMBER_KIND: switch (c_fpclassify(the->stack->value.number)) { case FP_NAN: case FP_ZERO: result = 0; break; default: result = 1; break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: if (c_strlen(the->stack->value.string) == 0) result = 0; else result = 1; break; default: result = 1; break; } the->stack++; return result; }
void fx_Date_prototype_set_aux(txMachine* the, txTimeDescription* td, txSlot* slot) { c_time_t time; txNumber number; td->tm.tm_isdst = -1; time = c_mktime(&(td->tm)); if (time == -1) number = C_NAN; else { number = (time * 1000.0) + td->ms; if (c_fpclassify(number) != FP_NAN) { if (c_fabs(number) > 8.64e15) number = C_NAN; else number = c_trunc(number); } } mxResult->value.number = number; mxResult->kind = XS_NUMBER_KIND; slot->value.number = number; }
txUnsigned fxToUnsigned(txMachine* the, txSlot* theSlot) { txUnsigned result; again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_INTEGER_KIND; result = theSlot->value.integer = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_INTEGER_KIND; if (theSlot->value.boolean == 0) result = theSlot->value.integer = 0; else result = theSlot->value.integer = 1; break; case XS_INTEGER_KIND: if (theSlot->value.integer >= 0) return (txUnsigned)theSlot->value.integer; theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = theSlot->value.integer; // continue case XS_NUMBER_KIND: theSlot->kind = XS_INTEGER_KIND; switch (c_fpclassify(theSlot->value.number)) { case C_FP_INFINITE: case C_FP_NAN: case C_FP_ZERO: result = theSlot->value.integer = 0; break; default: { #define MODULO 4294967296.0 txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO); if (aNumber < 0) aNumber += MODULO; result = (txUnsigned)aNumber; if (((txInteger)result) >= 0) { theSlot->kind = XS_INTEGER_KIND; theSlot->value.integer = (txInteger)result; } else { theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = aNumber; } } break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); goto again; case XS_SYMBOL_KIND: result = 0; mxTypeError("Cannot coerce symbol to unsigned"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: result = 0; mxTypeError("Cannot coerce to unsigned"); break; } return result; }