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_xs_debug_setBreakpoint(txMachine* the) { if ((mxArgc < 1) || (!mxIsStringPrimitive(mxArgv(0)))) mxTypeError("file is no string"); if ((mxArgc < 2) || (!mxIsStringPrimitive(mxArgv(1)))) mxTypeError("line is no string"); fxSetBreakpoint(the, mxArgv(0)->value.string, mxArgv(1)->value.string); }
void fx_xs_isInstanceOf(txMachine* the) { if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND)) mxTypeError("instance is no object"); if ((mxArgc < 2) || (mxArgv(1)->kind != XS_REFERENCE_KIND)) mxTypeError("prototype is no object"); mxPushSlot(mxArgv(1)); mxPushSlot(mxArgv(0)); mxResult->value.boolean = fxIsInstanceOf(the); mxResult->kind = XS_BOOLEAN_KIND; }
txSlot* fxToInstance(txMachine* the, txSlot* theSlot) { txSlot* anInstance = C_NULL; switch (theSlot->kind) { case XS_UNDEFINED_KIND: mxTypeError("cannot coerce undefined to object"); break; case XS_NULL_KIND: mxTypeError("cannot coerce null to object"); break; case XS_BOOLEAN_KIND: mxPush(mxBooleanPrototype); anInstance = fxNewBooleanInstance(the); anInstance->next->value.boolean = theSlot->value.boolean; mxPullSlot(theSlot); break; case XS_INTEGER_KIND: mxPush(mxNumberPrototype); anInstance = fxNewNumberInstance(the); anInstance->next->value.number = theSlot->value.integer; mxPullSlot(theSlot); break; case XS_NUMBER_KIND: mxPush(mxNumberPrototype); anInstance = fxNewNumberInstance(the); anInstance->next->value.number = theSlot->value.number; mxPullSlot(theSlot); break; case XS_STRING_KIND: case XS_STRING_X_KIND: mxPush(mxStringPrototype); anInstance = fxNewStringInstance(the); anInstance->next->value.string = theSlot->value.string; anInstance->next->next->next->value.integer = fxUnicodeLength(theSlot->value.string); mxPullSlot(theSlot); break; case XS_SYMBOL_KIND: mxPush(mxSymbolPrototype); anInstance = fxNewSymbolInstance(the); anInstance->next->value.ID = theSlot->value.ID; mxPullSlot(theSlot); break; case XS_REFERENCE_KIND: anInstance = theSlot->value.reference; break; default: mxTypeError("cannot coerce to instance"); break; } return anInstance; }
void fx_Date_prototype_valueOf(txMachine* the) { txSlot* slot = fxCheckDate(the, mxThis); if (!slot) mxTypeError("this is no date"); mxResult->kind = XS_NUMBER_KIND; mxResult->value = slot->value; }
void fx_Boolean_prototype_valueOf(txMachine* the) { txSlot* slot = fxCheckBoolean(the, mxThis); if (!slot) mxTypeError("this is no boolean"); mxResult->kind = slot->kind; mxResult->value = slot->value; }
txSlot* fx_Date_prototype_getUTC_aux(txMachine* the, txTimeDescription* td) { txSlot* slot = fxCheckDate(the, mxThis); txNumber number; c_time_t time; txInteger year = 0; if (!slot) mxTypeError("this is no date"); number = slot->value.number; if (c_isnan(number)) { mxResult->value.number = C_NAN; mxResult->kind = XS_NUMBER_KIND; return C_NULL; } c_memset(td, 0, sizeof(txTimeDescription)); td->tm.tm_mday = 1; td->ms = (int)c_floor(c_fmod(number, 1000.0)); number /= 1000.0; //if ((number < gxMinTime) || (gxMaxTime < number)) // mxTypeError("invalid time"); if(number > TIME_2032) { // 2032 <= number <= 2099 year = (int)((number - TIME_2032)/TIME_FourYear); number -= TIME_FourYear * year; year *= 4; } time = (c_time_t)c_floor(number); td->tm = *c_gmtime(&time); td->tm.tm_year += year; if( (td->ms < 0) && (td->ms > -1000) ) td->ms = 1000 + td->ms; mxResult->kind = XS_INTEGER_KIND; return slot; }
void fx_Function_prototype_hasInstance(txMachine* the) { txSlot* instance; txSlot* prototype; mxResult->value.boolean = 0; mxResult->kind = XS_BOOLEAN_KIND; if (mxArgc == 0) return; instance = fxGetInstance(the, mxArgv(0)); if (!instance) return; mxPushSlot(mxThis); fxGetID(the, mxID(_prototype)); prototype = fxGetInstance(the, the->stack); if (!prototype) mxTypeError("prototype is no object"); while (instance) { if (instance == prototype) { mxResult->value.boolean = 1; break; } instance = fxGetParent(the, instance); } the->stack++; }
void fx_Symbol_prototype_valueOf(txMachine* the) { txSlot* slot = fxCheckSymbol(the, mxThis); if (!slot) mxTypeError("this is no symbol"); mxResult->kind = slot->kind; mxResult->value = slot->value; }
void fx_Number_prototype_valueOf(txMachine* the) { txSlot* slot = fxCheckNumber(the, mxThis); if (!slot) mxTypeError("this is no number"); mxResult->kind = slot->kind; mxResult->value = slot->value; }
void fx_xs_newInstanceOf(txMachine* the) { if ((mxArgc < 1) || (mxArgv(0)->kind != XS_REFERENCE_KIND)) mxTypeError("prototype is no object"); mxPushSlot(mxArgv(0)); fxNewInstanceOf(the); mxPullSlot(mxResult); }
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_xs_debug_setConnected(txMachine* the) { if ((mxArgc < 1) || (mxArgv(0)->kind != XS_BOOLEAN_KIND)) mxTypeError("argument is no boolean"); if (mxArgv(0)->value.boolean) fxLogin(the); else fxLogout(the); }
txSlot* fxCheckFunctionInstance(txMachine* the, txSlot* slot) { if (slot->kind == XS_REFERENCE_KIND) { slot = slot->value.reference; if ((slot->next->kind == XS_CALLBACK_KIND) || (slot->next->kind == XS_CODE_KIND) || (slot->next->kind == XS_CODE_X_KIND)) return slot; } mxTypeError("this is no Function instance"); return C_NULL; }
txNumber fxToNumber(txMachine* the, txSlot* theSlot) { again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = C_NAN; break; case XS_NULL_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_NUMBER_KIND; if (theSlot->value.boolean == 0) theSlot->value.number = 0; else theSlot->value.number = 1; break; case XS_INTEGER_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = theSlot->value.integer; break; case XS_NUMBER_KIND: 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); break; case XS_SYMBOL_KIND: mxTypeError("Cannot coerce symbol to number"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: mxTypeError("Cannot coerce to number"); break; } return theSlot->value.number; }
void fx_Function_prototype_set_prototype(txMachine* the) { txSlot* instance = fxCheckFunctionInstance(the, mxThis); txSlot* slot = mxFunctionInstancePrototype(instance); if (slot->flag & XS_DONT_SET_FLAG) { if (the->frame->next->flag & XS_STRICT_FLAG) mxTypeError("set \"prototype\": const"); return; } if (instance->flag & XS_SHARED_FLAG) mxTypeError("set \"prototype\": shared"); if ((mxArgc == 0) || (mxArgv(0)->kind == XS_UNDEFINED_KIND) || (mxArgv(0)->kind == XS_NULL_KIND)) { slot->kind = XS_NULL_KIND; } else { fxToInstance(the, mxArgv(0)); slot->value = mxArgv(0)->value; slot->kind = mxArgv(0)->kind; } }
void fx_Date_prototype_toPrimitive(txMachine* the) { if (mxThis->kind == XS_REFERENCE_KIND) { txInteger hint = ((mxArgc > 0) && (c_strcmp(fxToString(the, mxArgv(0)), "number") == 0)) ? XS_NUMBER_HINT : XS_STRING_HINT; if (hint == XS_STRING_HINT) { mxPushInteger(0); mxPushSlot(mxThis); fxCallID(the, mxID(_toString)); if (mxIsReference(the->stack)) { the->stack++; mxPushInteger(0); mxPushSlot(mxThis); fxCallID(the, mxID(_valueOf)); } } else { mxPushInteger(0); mxPushSlot(mxThis); fxCallID(the, mxID(_valueOf)); if (mxIsReference(the->stack)) { the->stack++; mxPushInteger(0); mxPushSlot(mxThis); fxCallID(the, mxID(_toString)); } } if (mxIsReference(the->stack)) { if (hint == XS_STRING_HINT) mxTypeError("Cannot coerce object to string"); else mxTypeError("Cannot coerce object to number"); } mxResult->kind = the->stack->kind; mxResult->value = the->stack->value; the->stack++; } else { mxResult->kind = mxThis->kind; mxResult->value = mxThis->value; } }
void fxCall(txMachine* the) { txSlot* aFunction; aFunction = fxGetInstance(the, the->stack); if (!mxIsFunction(aFunction)) mxTypeError("C: xsCall: no function"); /* TARGET */ mxPushUndefined(); /* RESULT */ mxPushUndefined(); fxRunID(the, C_NULL, XS_NO_ID); }
void fx_Number_prototype_toPrecision(txMachine* the) { char buffer[256]; int precision; txSlot* slot = fxCheckNumber(the, mxThis); if (!slot) mxTypeError("this is no number"); if (mxArgc > 0) precision = fxToInteger(the, mxArgv(0)); else precision = 0; fxNumberToString(the->dtoa, slot->value.number, buffer, sizeof(buffer), 'g', precision); fxCopyStringC(the, mxResult, buffer); }
txSlot* fxArgToCallback(txMachine* the, txInteger argi) { if (mxArgc > argi) { txSlot* slot = mxArgv(argi); if (slot->kind == XS_REFERENCE_KIND) { slot = slot->value.reference; if (slot->next && ((slot->next->kind == XS_CODE_KIND) || (slot->next->kind == XS_CODE_X_KIND) || (slot->next->kind == XS_CALLBACK_KIND))) return slot; } } mxTypeError("callback is no function"); return C_NULL; }
void fx_Symbol_keyFor(txMachine* the) { txSlot* slot; txSlot* key; if (mxArgc < 1) mxSyntaxError("no sym parameter"); slot = fxCheckSymbol(the, mxArgv(0)); if (!slot) mxTypeError("sym is no symbol"); key = fxGetKey(the, slot->value.ID); if (key && ((key->flag & XS_DONT_ENUM_FLAG) == 0)) { mxResult->kind = XS_STRING_KIND; mxResult->value.string = key->value.key.string; } }
txString fxToString(txMachine* the, txSlot* theSlot) { char aBuffer[256]; again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: fxCopyStringC(the, theSlot, "undefined"); break; case XS_NULL_KIND: fxCopyStringC(the, theSlot, "null"); break; case XS_BOOLEAN_KIND: if (theSlot->value.boolean == 0) fxCopyStringC(the, theSlot, "false"); else fxCopyStringC(the, theSlot, "true"); break; case XS_INTEGER_KIND: fxCopyStringC(the, theSlot, fxIntegerToString(the->dtoa, theSlot->value.integer, aBuffer, sizeof(aBuffer))); break; case XS_NUMBER_KIND: fxCopyStringC(the, theSlot, fxNumberToString(the->dtoa, theSlot->value.number, aBuffer, sizeof(aBuffer), 0, 0)); break; case XS_SYMBOL_KIND: mxTypeError("Cannot coerce symbol to string"); break; case XS_STRING_KIND: case XS_STRING_X_KIND: break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_STRING_HINT); goto again; default: mxTypeError("Cannot coerce to string"); break; } return theSlot->value.string; }
void fx_Function_prototype_get_prototype(txMachine* the) { txSlot* instance = fxCheckFunctionInstance(the, mxThis); txSlot* slot = mxFunctionInstancePrototype(instance); if (slot->kind == XS_NULL_KIND) { if (slot->flag & XS_DONT_SET_FLAG) return; if (instance->flag & XS_SHARED_FLAG) mxTypeError("get \"prototype\": shared"); fxDefaultFunctionPrototype(the, instance, slot); } mxResult->kind = slot->kind; mxResult->value = slot->value; }
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; }
void fx_Symbol(txMachine* the) { txID id = the->keyIndex; txSlot* description; if (mxTarget->kind != XS_UNDEFINED_KIND) mxTypeError("new Symbol"); if (id == the->keyCount) mxUnknownError("not enough IDs"); if (mxArgc > 0) { fxToString(the, mxArgv(0)); description = fxNewSlot(the); description->kind = XS_STRING_KIND; description->value.string = mxArgv(0)->value.string; } else description = C_NULL; the->keyArray[id] = description; the->keyIndex++; mxResult->kind = XS_SYMBOL_KIND; mxResult->value.ID = 0x8000 | id; }
void fxNew(txMachine* the) { txSlot* aFunction; aFunction = fxGetInstance(the, the->stack); if (!mxIsFunction(aFunction)) mxTypeError("C: xsNew: no function"); /* THIS */ if (fxIsBaseFunctionInstance(the, aFunction)) fxCreateInstance(the, aFunction); else mxPushUninitialized(); /* FUNCTION */ the->scratch = *(the->stack); *(the->stack) = *(the->stack + 1); *(the->stack + 1) = the->scratch; /* TARGET */ --(the->stack); *(the->stack) = *(the->stack + 1); /* RESULT */ --(the->stack); *(the->stack) = *(the->stack + 3); fxRunID(the, C_NULL, XS_NO_ID); }
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; }
void fx_Function_prototype_bind(txMachine* the) { txSlot* instance = fxToInstance(the, mxThis); txSize length; txSlot* slot; txID id; txSlot* arguments; txSlot* argument; txSize c = mxArgc, i; if (!fxIsFunction(the, instance)) mxTypeError("this is no Function instance"); if (fxHasOwnProperty(the, instance, mxID(_length))) { mxPushSlot(mxThis); fxGetID(the, mxID(_length)); length = fxToInteger(the, the->stack++); if (c > 1) length -= c - 1; if (length < 0) length = 0; mxPop(); } else length = 0; mxPushSlot(mxThis); fxGetID(the, mxID(_name)); mxPushStringC("bound "); fxConcatString(the, the->stack, the->stack + 1); slot = fxNewName(the, the->stack); id = slot->ID; mxPop(); mxPop(); mxPushReference(instance->value.instance.prototype); instance = fxNewFunctionInstance(the, id); mxPullSlot(mxResult); slot = mxFunctionInstanceCode(instance); slot->kind = XS_CALLBACK_KIND; slot->value.callback.address = fx_Function_prototype_bound; slot->value.callback.IDs = (txID*)mxIDs.value.code; slot = mxFunctionInstanceInfo(instance); slot->value.info.length = (txID)length; slot = fxLastProperty(the, instance); slot = fxNextSlotProperty(the, slot, mxThis, mxID(_boundFunction), XS_GET_ONLY); if (c > 0) slot = fxNextSlotProperty(the, slot, mxArgv(0), mxID(_boundThis), XS_GET_ONLY); else slot = fxNextUndefinedProperty(the, slot, mxID(_boundThis), XS_GET_ONLY); mxPush(mxArrayPrototype); arguments = fxNewArrayInstance(the); argument = arguments->next; for (i = 1; i < c; i++) { argument->next = fxNewSlot(the); argument = argument->next; argument->kind = mxArgv(i)->kind; argument->value = mxArgv(i)->value; } arguments->next->value.array.length = mxArgc - 1; fxCacheArray(the, arguments); slot = fxNextSlotProperty(the, slot, the->stack, mxID(_boundArguments), XS_GET_ONLY); mxPop(); }
void fx_Function_prototype_set_name(txMachine* the) { if (the->frame->next->flag & XS_STRICT_FLAG) mxTypeError("set \"name\": const"); }