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; }
txSlot* fxConstructArrayResult(txMachine* the, txSlot* constructor, txUnsigned length) { mxPushUnsigned(length); mxPushInteger(1); if (constructor) { mxPushSlot(constructor); fxGetID(the, mxID(_Symbol_species)); } else { txSlot* instance = mxThis->value.reference; if (mxIsArray(instance)) { mxPushSlot(mxThis); fxGetID(the, mxID(_constructor)); if (mxIsReference(the->stack) && mxIsFunction(the->stack->value.reference)) fxGetID(the, mxID(_Symbol_species)); else the->stack->kind = XS_UNDEFINED_KIND; } else mxPushUndefined(); } if (the->stack->kind == XS_NULL_KIND) the->stack->kind = XS_UNDEFINED_KIND; if (the->stack->kind == XS_UNDEFINED_KIND) { *the->stack = mxGlobal; fxGetID(the, mxID(_Array)); } fxNew(the); mxPullSlot(mxResult); return mxResult->value.reference->next; }
void fx_Function_prototype_bound(txMachine* the) { txSlot* boundArguments; txInteger c, i; txSlot* argument; mxPush(*mxFunction); fxGetID(the, mxID(_boundArguments)); boundArguments = fxGetInstance(the, the->stack); the->stack++; c = boundArguments->next->value.array.length; argument = boundArguments->next->value.array.address; for (i = 0; i < c; i++) { mxPushSlot(argument); argument++; } for (i = 0; i < mxArgc; i++) { mxPushSlot(mxArgv(i)); } /* ARGC */ mxPushInteger(c + mxArgc); /* THIS */ mxPushSlot(mxFunction); fxGetID(the, mxID(_boundThis)); /* FUNCTION */ mxPushSlot(mxFunction); fxGetID(the, mxID(_boundFunction)); fxCall(the); mxPullSlot(mxResult); }
void fx_Function_prototype_apply(txMachine* the) { txInteger c, i; if ((mxArgc < 2) || (mxArgv(1)->kind == XS_UNDEFINED_KIND) || (mxArgv(1)->kind == XS_NULL_KIND)) c = 0; else { fxToInstance(the, mxArgv(1)); mxPushSlot(mxArgv(1)); fxGetID(the, mxID(_length)); c = fxToInteger(the, the->stack); the->stack++; for (i = 0; i < c; i++) { mxPushSlot(mxArgv(1)); fxGetID(the, (txID)i); } } /* ARGC */ mxPushInteger(c); /* THIS */ if (mxArgc < 1) mxPushUndefined(); else mxPushSlot(mxArgv(0)); /* FUNCTION */ mxPushSlot(mxThis); fxCall(the); mxPullSlot(mxResult); }
void fx_Error_toString(txMachine* the) { txInteger aLength; mxPushSlot(mxThis); fxGetID(the, mxID(_name)); if (the->stack->kind == XS_UNDEFINED_KIND) fxCopyStringC(the, the->stack, "Error"); else fxToString(the, the->stack); mxPushSlot(mxThis); fxGetID(the, mxID(_message)); if (the->stack->kind == XS_UNDEFINED_KIND) fxCopyStringC(the, the->stack, ""); else fxToString(the, the->stack); aLength = c_strlen(the->stack->value.string); if (aLength) { aLength += c_strlen((the->stack + 1)->value.string) + 2; mxResult->value.string = (txString)fxNewChunk(the, aLength + 1); mxResult->kind = XS_STRING_KIND; c_strcpy(mxResult->value.string, (the->stack + 1)->value.string); c_strcat(mxResult->value.string, ": "); c_strcat(mxResult->value.string, the->stack->value.string); the->stack++; the->stack++; } else { the->stack++; mxPullSlot(mxResult); } }
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_Error(txMachine* the) { if (mxTarget->kind == XS_UNDEFINED_KIND) { mxPush(mxErrorPrototype); fxNewObjectInstance(the); mxPullSlot(mxResult); } fx_Error_aux(the); }
void fx_Enumerator(txMachine* the) { txSlot* iterator; if (mxThis->kind == XS_REFERENCE_KIND) fxEnumerateInstance(the, mxThis->value.reference); else { mxPushSlot(mxFunctionInstancePrototype(mxEnumeratorFunction.value.reference)); iterator = fxNewIteratorInstance(the, mxThis); mxPullSlot(mxResult); iterator->next->next->next = C_NULL; } }
void fx_Array(txMachine* the) { txIndex count = (txIndex)mxArgc; txBoolean flag = 0; txSlot* instance; txSlot* array; txSlot* argument; txSlot* slot; if (mxTarget->kind == XS_UNDEFINED_KIND) { mxPush(mxArrayPrototype); instance = fxNewArrayInstance(the); mxPullSlot(mxResult); array = instance->next; } else array = fxCoerceToArray(the, mxThis); flag = 0; if (count == 1) { argument = mxArgv(0); if (argument->kind == XS_INTEGER_KIND) { flag = 1; if ((0 <= argument->value.integer) && (argument->value.integer < XS_MAX_INDEX)) count = (txIndex)argument->value.integer; else mxRangeError("invalid length"); } else if (mxArgv(0)->kind == XS_NUMBER_KIND) { flag = 1; if ((0 <= argument->value.number) && (argument->value.number < XS_MAX_INDEX)) count = (txIndex)argument->value.number; else mxRangeError("invalid length"); } } array->value.array.address = (txSlot *)fxNewChunk(the, count * sizeof(txSlot)); array->value.array.length = count; slot = array->value.array.address; if (flag) { c_memset(slot, 0, count * sizeof(txSlot)); } else { txIndex index = 0; while (index < count) { txSlot* argument = mxArgv(index); slot->ID = XS_NO_ID; slot->kind = argument->kind; slot->value = argument->value; slot++; index++; } } }
void fx_JSON_parse(txMachine* the) { volatile txJSONParser* aParser = C_NULL; txSlot* slot; mxTry(the) { if (mxArgc < 1) mxSyntaxError("no buffer"); aParser = c_malloc(sizeof(txJSONParser)); if (NULL == aParser) mxUnknownError("out of memory"); c_memset((txJSONParser*)aParser, 0, sizeof(txJSONParser)); if (mxArgc > 1) { slot = mxArgv(1); 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))) aParser->reviver = slot; } } slot = mxArgv(0); if (slot->kind == XS_REFERENCE_KIND) { slot = slot->value.reference->next; if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_HOST_KIND)) { aParser->data = slot->value.host.data; aParser->offset = 0; mxPushSlot(mxArgv(0)); fxGetID(the, mxID(_length)); aParser->size = fxToInteger(the, the->stack++); } } if (!aParser->data) { fxToString(the, mxArgv(0)); aParser->slot = mxArgv(0); aParser->offset = 0; aParser->size = c_strlen(aParser->slot->value.string); } fxParseJSON(the, (txJSONParser*)aParser); mxPullSlot(mxResult); c_free((txJSONParser*)aParser); // @@ reviver } mxCatch(the) { if (aParser) c_free((txJSONParser*)aParser); fxJump(the); } }
void fx_Function(txMachine* the) { txInteger c, i; txStringStream stream; c = mxArgc; i = 0; mxPushStringC("(function anonymous("); while (c > 1) { fxToString(the, mxArgv(i)); fxConcatString(the, the->stack, mxArgv(i)); if (c > 2) fxConcatStringC(the, the->stack, ", "); c--; i++; } fxConcatStringC(the, the->stack, "){"); if (c > 0) { fxToString(the, mxArgv(i)); fxConcatString(the, the->stack, mxArgv(i)); } fxConcatStringC(the, the->stack, "})"); stream.slot = the->stack; stream.offset = 0; stream.size = c_strlen(the->stack->value.string); fxRunScript(the, fxParseScript(the, &stream, fxStringGetter, mxProgramFlag), C_NULL, C_NULL, C_NULL, C_NULL); if (mxTarget->kind == XS_UNDEFINED_KIND) mxPullSlot(mxResult); else { txSlot* from = fxGetInstance(the, the->stack++); txSlot* to = fxGetInstance(the, mxThis); txSlot* fromProperty; txSlot* toProperty; to->next->value.code = from->next->value.code; fromProperty = mxFunctionInstancePrototype(from); toProperty = mxFunctionInstancePrototype(to); *toProperty = *fromProperty; fromProperty = mxFunctionInstanceInfo(from); toProperty = mxFunctionInstanceInfo(to); *toProperty = *fromProperty; } }
void fx_Function_prototype_call(txMachine* the) { txInteger c, i; c = mxArgc; i = 1; while (i < c) { mxPushSlot(mxArgv(i)); i++; } /* ARGC */ mxPushInteger(i - 1); /* THIS */ if (mxArgc < 1) mxPushUndefined(); else mxPushSlot(mxArgv(0)); /* FUNCTION */ mxPushSlot(mxThis); fxCall(the); mxPullSlot(mxResult); }
void fxReduceArrayItem(txMachine* the, txSlot* function, txSlot* array, txIndex index) { txSlot* slot = array->value.array.address + index; if (slot->ID) { /* ARG0 */ mxPushSlot(mxResult); /* ARG1 */ mxPushSlot(slot); /* ARG2 */ mxPushUnsigned(index); /* ARG3 */ mxPushSlot(mxThis); /* ARGC */ mxPushInteger(4); /* THIS */ mxPushUndefined(); /* FUNCTION */ mxPushReference(function); fxCall(the); mxPullSlot(mxResult); } }
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 fxSerializeJSONProperty(txMachine* the, txJSONSerializer* theSerializer, txInteger* theFlag) { txSlot* aWrapper = the->stack + 2; txSlot* aValue = the->stack + 1; txSlot* aKey = the->stack; txSlot* anInstance; txSlot* aProperty; txInteger aFlag; txIndex aLength, anIndex; if (mxIsReference(aValue)) { anInstance = fxGetInstance(the, aValue); if (anInstance->flag & XS_LEVEL_FLAG) mxTypeError("cyclic value"); mxPushSlot(aKey); /* COUNT */ mxPushInteger(1); /* THIS */ mxPushSlot(aValue); /* FUNCTION */ mxPushSlot(aValue); fxGetID(the, mxID(_toJSON)); if (mxIsReference(the->stack) && mxIsFunction(the->stack->value.reference)) { fxCall(the); mxPullSlot(aValue); } else { the->stack = aKey; } } else anInstance = C_NULL; if (theSerializer->replacer) { mxPushSlot(aKey); mxPushSlot(aValue); /* COUNT */ mxPushInteger(2); /* THIS */ mxPushSlot(aWrapper); /* FUNCTION */ mxPushSlot(theSerializer->replacer); fxCall(the); mxPullSlot(aValue); } again: switch (aValue->kind) { case XS_NULL_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONChars(the, theSerializer, "null"); break; case XS_BOOLEAN_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONChars(the, theSerializer, aValue->value.boolean ? "true" : "false"); break; case XS_INTEGER_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONInteger(the, theSerializer, aValue->value.integer); break; case XS_NUMBER_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONNumber(the, theSerializer, aValue->value.number); break; case XS_STRING_KIND: case XS_STRING_X_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONString(the, theSerializer, aValue->value.string); break; case XS_ARRAY_KIND: fxSerializeJSONName(the, theSerializer, theFlag); anInstance->flag |= XS_LEVEL_FLAG; fxSerializeJSONChar(the, theSerializer, '['); theSerializer->level++; fxSerializeJSONIndent(the, theSerializer); aFlag = 4; aLength = aValue->value.array.length; for (anIndex = 0; anIndex < aLength; anIndex++) { aProperty = aValue->value.array.address + anIndex; mxPushSlot(aProperty); mxPushInteger(anIndex); fxSerializeJSONProperty(the, theSerializer, &aFlag); } theSerializer->level--; fxSerializeJSONIndent(the, theSerializer); fxSerializeJSONChar(the, theSerializer, ']'); anInstance->flag &= ~XS_LEVEL_FLAG; break; case XS_REFERENCE_KIND: anInstance = fxGetInstance(the, aValue); aValue = anInstance->next; if (aValue && (aValue->flag & XS_INTERNAL_FLAG) && (aValue->kind != XS_PROXY_KIND)) { goto again; } fxSerializeJSONName(the, theSerializer, theFlag); anInstance->flag |= XS_LEVEL_FLAG; if (fxIsArray(the, anInstance)) { fxSerializeJSONChar(the, theSerializer, '['); theSerializer->level++; fxSerializeJSONIndent(the, theSerializer); aFlag = 4; mxPushReference(anInstance); fxGetID(the, mxID(_length)); aLength = fxToInteger(the, the->stack); mxPop(); for (anIndex = 0; anIndex < aLength; anIndex++) { mxPushReference(anInstance); fxGetID(the, anIndex); mxPushInteger(anIndex); fxSerializeJSONProperty(the, theSerializer, &aFlag); } theSerializer->level--; fxSerializeJSONIndent(the, theSerializer); fxSerializeJSONChar(the, theSerializer, ']'); } else { fxSerializeJSONChar(the, theSerializer, '{'); theSerializer->level++; fxSerializeJSONIndent(the, theSerializer); aFlag = 2; { txSlot aContext; aContext.value.regexp.code = theSerializer; aContext.value.regexp.offsets = &aFlag; fxEachInstanceProperty(the, anInstance, XS_EACH_ENUMERABLE_FLAG | XS_EACH_STRING_FLAG | XS_STEP_GET_FLAG, fxSerializeJSONOwnProperty, &aContext, anInstance); } theSerializer->level--; fxSerializeJSONIndent(the, theSerializer); fxSerializeJSONChar(the, theSerializer, '}'); } anInstance->flag &= ~XS_LEVEL_FLAG; break; default: if (*theFlag & 4) { if (*theFlag & 1) { fxSerializeJSONChars(the, theSerializer, ","); fxSerializeJSONIndent(the, theSerializer); } else *theFlag |= 1; fxSerializeJSONChars(the, theSerializer, "null"); } break; } the->stack++; // POP VALUE }