txMachine* fxBeginHost(txMachine* the) { /* ARGC */ mxPushInteger(0); /* THIS */ mxPush(mxGlobal); /* FUNCTION */ mxPushUndefined(); /* TARGET */ mxPushUndefined(); /* RESULT */ mxPushUndefined(); /* FRAME */ --the->stack; the->stack->next = the->frame; the->stack->ID = XS_NO_ID; the->stack->flag = XS_C_FLAG; the->stack->kind = XS_FRAME_KIND; the->stack->value.frame.code = the->code; the->stack->value.frame.scope = the->scope; the->frame = the->stack; /* VARC */ mxPushInteger(0); the->stack->next = C_NULL; the->stack->ID = XS_NO_ID; the->stack->kind = XS_INTEGER_KIND; the->scope = the->stack; the->code = mxIDs.value.code; return the; }
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); }
txBoolean fxCallArrayItem(txMachine* the, txSlot* function, txSlot* array, txIndex index, txSlot* item) { txSlot* slot = array->value.array.address + index; if (slot->ID) { /* ARG0 */ mxPushSlot(slot); if (item) { item->kind = the->stack->kind; item->value = the->stack->value; } /* ARG1 */ mxPushUnsigned(index); /* ARG2 */ mxPushSlot(mxThis); /* ARGC */ mxPushInteger(3); /* THIS */ if (mxArgc > 1) mxPushSlot(mxArgv(1)); else mxPushUndefined(); /* FUNCTION */ mxPushReference(function); fxCall(the); return 1; } return 0; }
void fxCallID(txMachine* the, txInteger theID) { mxPushUndefined(); *the->stack = *(the->stack + 1); fxGetID(the, theID); fxCall(the); }
txSlot* fxNewHostObject(txMachine* the, txDestructor theDestructor) { txSlot* anInstance; txSlot* aProperty; mxPushUndefined(); anInstance = fxNewSlot(the); anInstance->flag = XS_VALUE_FLAG; anInstance->kind = XS_INSTANCE_KIND; anInstance->value.instance.garbage = C_NULL; anInstance->value.instance.prototype = mxObjectPrototype.value.reference; the->stack->value.reference = anInstance; the->stack->kind = XS_REFERENCE_KIND; aProperty = anInstance->next = fxNewSlot(the); aProperty->ID = XS_NO_ID; aProperty->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; aProperty->kind = XS_HOST_KIND; aProperty->value.host.data = C_NULL; aProperty->value.host.variant.destructor = theDestructor; if (the->frame && (mxFunction->kind == XS_REFERENCE_KIND)) { txSlot* slot = mxFunctionInstanceModule(mxFunction->value.reference); aProperty = aProperty->next = fxNewSlot(the); aProperty->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; aProperty->kind = slot->kind; aProperty->value = slot->value; } return anInstance; }
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); }
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 fxSerializeJSON(txMachine* the, txJSONSerializer* theSerializer) { txSlot* aSlot; txInteger aFlag; aSlot = fxGetInstance(the, mxThis); theSerializer->offset = 0; theSerializer->size = 1024; theSerializer->buffer = c_malloc(1024); if (!theSerializer->buffer) mxUnknownError("out of memory"); if (mxArgc > 1) { aSlot = mxArgv(1); if (mxIsReference(aSlot)) { aSlot = fxGetInstance(the, aSlot); if (mxIsFunction(aSlot)) theSerializer->replacer = mxArgv(1); else if (mxIsArray(aSlot)) mxSyntaxError("not yet implememented"); } } if (mxArgc > 2) { aSlot = mxArgv(2); if (mxIsReference(aSlot)) { aSlot = fxGetInstance(the, aSlot); if (mxIsNumber(aSlot) || mxIsString(aSlot)) aSlot = aSlot->next; } if ((aSlot->kind == XS_INTEGER_KIND) || (aSlot->kind == XS_NUMBER_KIND)) { txInteger aCount = fxToInteger(the, aSlot), anIndex; if (aCount < 0) aCount = 0; else if (aCount > 10) aCount = 10; for (anIndex = 0; anIndex < aCount; anIndex++) theSerializer->indent[anIndex] = ' '; } else if (mxIsStringPrimitive(aSlot)) c_strncpy((char *)theSerializer->indent, aSlot->value.string, 10); } theSerializer->stack = the->stack; mxPush(mxObjectPrototype); fxNewObjectInstance(the); aFlag = 0; if (mxArgc > 0) mxPushSlot(mxArgv(0)); else mxPushUndefined(); mxPush(mxEmptyString); fxSerializeJSONProperty(the, theSerializer, &aFlag); the->stack++; }
void fxVars(txMachine* the, txInteger theCount) { txSlot* aStack = the->frame - 1; if (aStack != the->stack) mxSyntaxError("C: xsVars: too late"); fxOverflow(the, theCount, C_NULL, 0); aStack->value.integer = theCount; while (theCount) { mxPushUndefined(); theCount--; } }
void fxModuleURL(txMachine* the) { txID id = fxCurrentModuleID(the); if (id != XS_NO_ID) { txSlot* key = fxGetKey(the, id); if (key->kind == XS_KEY_KIND) mxPushString(key->value.key.string); else mxPushStringX(key->value.key.string); } else { mxPushUndefined(); } }
void fx_setTimeoutCallback(CFRunLoopTimerRef timer, void *info) { txTimeoutData* data = info; txMachine* the = data->the; fxBeginHost(the); { mxPush(data->argument); /* ARGC */ mxPushInteger(1); /* THIS */ mxPushUndefined(); /* FUNCTION */ mxPush(data->function); fxCall(the); the->stack++; } fxEndHost(the); }
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 fxParseJSONValue(txMachine* the, txJSONParser* theParser) { switch (theParser->token) { case XS_JSON_TOKEN_FALSE: mxPushBoolean(0); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_TRUE: mxPushBoolean(1); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_NULL: mxPushNull(); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_INTEGER: mxPushInteger(theParser->integer); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_NUMBER: mxPushNumber(theParser->number); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_STRING: mxPushString(theParser->string->value.string); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_LEFT_BRACE: fxParseJSONObject(the, theParser); break; case XS_JSON_TOKEN_LEFT_BRACKET: fxParseJSONArray(the, theParser); break; default: mxPushUndefined(); mxSyntaxError("invalid value"); break; } }
txSlot* fxCreateInstance(txMachine* the, txSlot* slot) { txSlot* prototype; mxPushUndefined(); prototype = the->stack; fxBeginHost(the); mxPushReference(slot); fxGetID(the, mxID(_prototype)); *prototype = *the->stack; fxEndHost(the); /* txSlot* prototype = mxFunctionInstancePrototype(slot); if (prototype->kind == XS_NULL_KIND) { if (prototype->flag & XS_DONT_SET_FLAG) mxTypeError("new.target: no constructor"); if (slot->flag & XS_SHARED_FLAG) mxTypeError("new.target: shared"); fxDefaultFunctionPrototype(the, slot, prototype); } mxPushSlot(prototype); */ fxNewInstanceOf(the); return the->stack->value.reference; }
txMachine* fxCreateMachine(txCreation* theCreation, void* theArchive, txString theName, void* theContext) { txMachine* the = (txMachine* )c_calloc(sizeof(txMachine), 1); if (the) { txJump aJump; aJump.nextJump = C_NULL; aJump.stack = C_NULL; aJump.scope = C_NULL; aJump.frame = C_NULL; aJump.code = C_NULL; aJump.flag = 0; the->firstJump = &aJump; if (c_setjmp(aJump.buffer) == 0) { txInteger anIndex; #if __FSK_LAYER__ FskInstrumentedItemNew(the, NULL, &gXSTypeInstrumentation); #endif #ifdef mxDebug the->echoSize = 1 * 1024; the->echoBuffer = (txString)c_malloc(the->echoSize); if (!the->echoBuffer) fxJump(the); //fxConnect(the); the->connection = mxNoSocket; the->name = theName; the->sorter = (txSlot**)c_malloc(theCreation->keyCount * sizeof(txSlot*)); if (!the->sorter) fxJump(the); the->breakOnExceptionFlag = 1; #endif #ifdef mxProfile the->profileID = 1; the->profileBottom = c_malloc(XS_PROFILE_COUNT * sizeof(txProfileRecord)); if (!the->profileBottom) fxJump(the); the->profileCurrent = the->profileBottom; the->profileTop = the->profileBottom + XS_PROFILE_COUNT; #endif the->archive = theArchive; the->dtoa = fxNew_dtoa(); if (!the->dtoa) fxJump(the); fxAllocate(the, theCreation); /* mxGLobal */ mxPushUndefined(); /* mxException */ mxPushUndefined(); for (anIndex = mxObjectPrototypeStackIndex; anIndex < mxModulePathsStackIndex; anIndex++) mxPushUndefined(); /* mxModulePaths */ mxPushUndefined(); /* mxImportingModules */ fxNewInstance(the); /* mxLoadingModules */ fxNewInstance(the); /* mxLoadedModules */ fxNewInstance(the); /* mxResolvingModules */ fxNewInstance(the); /* mxRunningModules */ fxNewInstance(the); /* mxRequiredModules */ fxNewInstance(the); /* mxModules */ mxPushUndefined(); /* mxPendingJobs */ fxNewInstance(the); /* mxRunningJobs */ fxNewInstance(the); /* mxFiles */ mxPushList(); /* mxBreakpoints */ mxPushList(); /* mxHosts */ mxPushUndefined(); /* mxIDs */ mxPushUndefined(); /* mxEmptyCode */ mxPushUndefined(); the->stack->value.code = (txByte *)fxNewChunk(the, sizeof(gxNoCode)); c_memcpy(the->stack->value.code, gxNoCode, sizeof(gxNoCode)); the->stack->kind = XS_CODE_KIND; /* mxEmptyString */ mxPushStringC(""); /* mxBooleanString */ mxPushStringC("boolean"); /* mxDefaultString */ mxPushStringC("default"); /* mxFunctionString */ mxPushStringC("function"); /* mxNumberString */ mxPushStringC("number"); /* mxObjectString */ mxPushStringC("object"); /* mxStringString */ mxPushStringC("string"); /* mxSymbolString */ mxPushStringC("symbol"); /* mxUndefinedString */ mxPushStringC("undefined"); for (anIndex = mxGetArgumentFunctionStackIndex; anIndex < mxStackIndexCount; anIndex++) mxPushUndefined(); fxBuildKeys(the); fxBuildGlobal(the); fxBuildObject(the); fxBuildFunction(the); fxBuildGenerator(the); fxBuildArray(the); fxBuildString(the); fxBuildBoolean(the); fxBuildNumber(the); fxBuildDate(the); fxBuildMath(the); fxBuildRegExp(the); fxBuildError(the); fxBuildJSON(the); fxBuildDataView(the); fxBuildPromise(the); fxBuildSymbol(the); fxBuildProxy(the); fxBuildMapSet(the); fxBuildModule(the); fxBuildHost(the); mxPush(mxSetPrototype); fxNewSetInstance(the); mxPull(mxModulePaths); mxPush(mxObjectPrototype); fxNewWeakSetInstance(the); mxPull(mxModules); the->collectFlag = XS_COLLECTING_FLAG; /*{ int c = 32; while (--c) fxCollectGarbage(the); }*/ the->context = theContext; #ifdef mxDebug if (fxGetAutomatic(the)) fxLogin(the); #endif the->firstJump = C_NULL; } else { #if __FSK_LAYER__ FskInstrumentedItemDispose(the); #endif fxFree(the); c_free(the); the = NULL; } } return the; }
void fx_Array_from(txMachine* the) { txSlot* list = fxNewInstance(the); txSlot* item = list; txIndex count = 0; txIndex index; txSlot* function = C_NULL; txSlot* _this = C_NULL; txSlot* resultArray; txSlot* resultSlot; if (mxArgc > 2) _this = mxArgv(2); if (mxArgc > 1) { txSlot* slot = mxArgv(1); if (slot->kind == XS_REFERENCE_KIND) { slot = slot->value.reference; if ((slot->next->kind == XS_CODE_KIND) || (slot->next->kind == XS_CALLBACK_KIND)) function = slot; } } if (mxArgc > 0) { mxPushSlot(mxArgv(0)); if (fxHasID(the, mxID(_Symbol_iterator))) { txSlot* iterator; txSlot* result; mxPushInteger(0); mxPushSlot(mxArgv(0)); fxCallID(the, mxID(_Symbol_iterator)); iterator = the->stack; { mxTry(the) { count = 0; for(;;) { mxCallID(iterator, mxID(_next), 0); result = the->stack; mxGetID(result, mxID(_done)); if (fxToBoolean(the, the->stack)) break; the->stack++; mxGetID(result, mxID(_value)); if (function) { /* ARG1 */ mxPushInteger(count); /* ARGC */ mxPushInteger(2); /* THIS */ if (_this) mxPushSlot(_this); else mxPushUndefined(); /* FUNCTION */ mxPushReference(function); fxCall(the); } item = fxNextSlotProperty(the, item, the->stack, XS_NO_ID, XS_NO_FLAG); the->stack++; count++; } } mxCatch(the) { mxCallID(iterator, mxID(_return), 0); fxJump(the); } } the->stack++; } else {
txSlot* fxNewHostFunction(txMachine* the, txCallback theCallback, txInteger theLength, txInteger name) { txSlot* instance; txSlot* property; mxPushUndefined(); instance = fxNewSlot(the); instance->flag = XS_VALUE_FLAG; instance->kind = XS_INSTANCE_KIND; instance->value.instance.garbage = C_NULL; instance->value.instance.prototype = mxFunctionPrototype.value.reference; the->stack->value.reference = instance; the->stack->kind = XS_REFERENCE_KIND; /* CALLBACK */ property = instance->next = fxNewSlot(the); property->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; property->kind = XS_CALLBACK_KIND; property->value.callback.address = theCallback; property->value.callback.IDs = (txID*)the->code; /* CLOSURE */ property = property->next = fxNewSlot(the); property->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; property->kind = XS_NULL_KIND; /* HOME */ property = property->next = fxNewSlot(the); property->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; property->kind = XS_NULL_KIND; /* MODULE */ property = property->next = fxNewSlot(the); property->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; if (the->frame && (mxFunction->kind == XS_REFERENCE_KIND)) { txSlot* slot = mxFunctionInstanceModule(mxFunction->value.reference); property->kind = slot->kind; property->value = slot->value; } else property->kind = XS_NULL_KIND; #ifdef mxProfile /* PROFILE */ property = property->next = fxNewSlot(the); property->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; property->kind = XS_INTEGER_KIND; property->value.integer = the->profileID; the->profileID++; #endif /* LENGTH */ property = property->next = fxNewSlot(the); property->flag = XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; property->ID = mxID(_length); property->kind = XS_INTEGER_KIND; property->value.integer = theLength; /* NAME */ property = property->next = fxNewSlot(the); property->flag = XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; property->ID = mxID(_name); property->kind = mxEmptyString.kind; property->value = mxEmptyString.value; if (name != XS_NO_ID) fxRenameFunction(the, property, name, "", C_NULL); return instance; }
txMachine* fxCloneMachine(txCreation* theCreation, txMachine* theMachine, txString theName, void* theContext) { txMachine* the = (txMachine *)c_calloc(sizeof(txMachine), 1); if (the) { txJump aJump; aJump.nextJump = C_NULL; aJump.stack = C_NULL; aJump.scope = C_NULL; aJump.frame = C_NULL; aJump.code = C_NULL; aJump.flag = 0; the->firstJump = &aJump; if (c_setjmp(aJump.buffer) == 0) { txInteger anIndex; txSlot* aSlot; txSlot** aSlotAddress; txSlot* aSharedSlot; txSlot* aTemporarySlot; txID anID; #if __FSK_LAYER__ FskInstrumentedItemNew(the, theName, &gXSTypeInstrumentation); #endif #ifdef mxDebug the->echoSize = 1 * 1024; the->echoBuffer = (txString)c_malloc(the->echoSize); if (!the->echoBuffer) fxJump(the); //fxConnect(the); the->name = theName; the->sorter = (txSlot**)c_malloc(theCreation->keyCount * sizeof(txSlot*)); if (!the->sorter) fxJump(the); the->breakOnExceptionFlag = 1; #endif #ifdef mxProfile the->profileID = theMachine->profileID; the->profileBottom = c_malloc(XS_PROFILE_COUNT * sizeof(txProfileRecord)); if (!the->profileBottom) fxJump(the); the->profileCurrent = the->profileBottom; the->profileTop = the->profileBottom + XS_PROFILE_COUNT; #endif the->archive = theMachine->archive; the->dtoa = fxNew_dtoa(); if (!the->dtoa) fxJump(the); theCreation->keyCount = theMachine->keyCount; theCreation->nameModulo = theMachine->nameModulo; theCreation->symbolModulo = theMachine->symbolModulo; fxAllocate(the, theCreation); the->sharedMachine = theMachine; c_memcpy(the->nameTable, theMachine->nameTable, the->nameModulo * sizeof(txSlot *)); c_memcpy(the->symbolTable, theMachine->symbolTable, the->symbolModulo * sizeof(txSlot *)); c_memcpy(the->keyArray, theMachine->keyArray, the->keyCount * sizeof(txSlot *)); the->keyIndex = theMachine->keyIndex; the->keyOffset = the->keyIndex; the->aliasCount = theMachine->aliasCount; the->aliasArray = (txSlot **)c_calloc(the->aliasCount, sizeof(txSlot*)); if (!the->aliasArray) fxJump(the); /* mxGlobal */ fxNewInstance(the); aSlot = the->stack->value.reference; aSlot->flag = XS_VALUE_FLAG; aSlot->next = fxNewSlot(the); aSlot = aSlot->next; aSlot->value.table.address = (txSlot**)fxNewChunk(the, theCreation->keyCount * sizeof(txSlot*)); aSlot->value.table.length = theCreation->keyCount; aSlot->kind = XS_GLOBAL_KIND; c_memset(aSlot->value.table.address, 0, theCreation->keyCount * sizeof(txSlot*)); aSlotAddress = aSlot->value.table.address; aSharedSlot = theMachine->stackTop[-1].value.reference->next->next; while (aSharedSlot) { aSlot->next = aTemporarySlot = fxDuplicateSlot(the, aSharedSlot); anID = aTemporarySlot->ID & 0x7FFF; aSlotAddress[anID] = aTemporarySlot; aSharedSlot = aSharedSlot->next; aSlot = aSlot->next; } /* mxException */ mxPushUndefined(); for (anIndex = mxObjectPrototypeStackIndex; anIndex < mxModulePathsStackIndex; anIndex++) *(--the->stack) = theMachine->stackTop[-1 - anIndex]; /* mxModulePaths */ mxPushUndefined(); /* mxImportingModules */ fxNewInstance(the); /* mxLoadingModules */ fxNewInstance(the); /* mxLoadedModules */ fxNewInstance(the); /* mxResolvingModules */ fxNewInstance(the); /* mxRunningModules */ fxNewInstance(the); /* mxRequiredModules */ fxNewInstance(the); /* mxModules */ mxPushUndefined(); /* mxPendingJobs */ fxNewInstance(the); /* mxRunningJobs */ fxNewInstance(the); /* mxFiles */ mxPushList(); #ifdef mxDebug aSharedSlot = theMachine->stackTop[-1 - mxFilesStackIndex].value.list.first; aSlotAddress = &(the->stack->value.list.first); while (aSharedSlot) { *aSlotAddress = fxDuplicateSlot(the, aSharedSlot); aSharedSlot = aSharedSlot->next; aSlotAddress = &((*aSlotAddress)->next); } #endif /* mxBreakpoints */ mxPushList(); /* shared */ for (anIndex = mxHostsStackIndex; anIndex < mxStackIndexCount; anIndex++) *(--the->stack) = theMachine->stackTop[-1 - anIndex]; mxPush(mxSetPrototype); fxNewSetInstance(the); mxPull(mxModulePaths); mxPush(mxObjectPrototype); fxNewWeakSetInstance(the); mxPull(mxModules); the->collectFlag = XS_COLLECTING_FLAG; the->context = theContext; #ifdef mxDebug if (fxGetAutomatic(the)) fxLogin(the); #endif the->firstJump = C_NULL; } else { #if __FSK_LAYER__ FskInstrumentedItemDispose(the); #endif fxFree(the); c_free(the); the = NULL; } } return the; }