void fxRunForIn(txMachine* the) { txSlot* limit = the->stack; txSlot* slot = fxToInstance(the, limit); while (slot) { fxEachInstanceProperty(the, slot, XS_EACH_ENUMERABLE_FLAG | XS_EACH_STRING_FLAG, fxRunForInProperty, limit, slot); slot = fxGetParent(the, slot); } slot = the->stack; while (slot < limit) { txInteger id = slot->value.integer; if (id < 0) { txSlot* key = fxGetKey(the, (txID)id); if (key && (key->flag & XS_DONT_ENUM_FLAG)) { if (key->kind == XS_KEY_KIND) { slot->kind = XS_STRING_KIND; slot->value.string = key->value.key.string; } else { slot->kind = XS_STRING_X_KIND; slot->value.string = key->value.key.string; } } else { slot->kind = XS_SYMBOL_KIND; slot->value.ID = (txID)id; } } slot++; } limit->kind = XS_NULL_KIND; }
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 }