FORCEINLINE PRT_BOOLEAN PrtIsSpecialEvent( _In_ PRT_VALUE *event ) { return (PrtIsNullValue(event) || PrtPrimGetEvent(event) == PRT_SPECIAL_EVENT_NULL); }
FORCEINLINE PRT_TYPE* PrtGetPayloadType( _In_ PRT_MACHINEINST_PRIV *context, _In_ PRT_VALUE *event ) { return context->process->program->events[PrtPrimGetEvent(event)].type; }
void PrtPopState( _Inout_ PRT_MACHINEINST_PRIV *context, _In_ PRT_BOOLEAN isPopStatement ) { PRT_UINT16 i; PRT_UINT16 packSize; PRT_UINT16 length; PRT_STATESTACK_INFO poppedState; i = 0; packSize = PrtGetPackSize(context); length = context->callStack.length; if (length == 0) { if (PrtPrimGetEvent(PrtGetCurrentTrigger(context)) == PRT_SPECIAL_EVENT_HALT) { PrtHaltMachine(context); } else { PrtHandleError(PRT_STATUS_EVENT_UNHANDLED, context); } return; } context->callStack.length = length - 1; poppedState = context->callStack.stateStack[length - 1]; context->currentState = poppedState.stateIndex; for (i = 0; i < packSize; i++) { context->inheritedDeferredSetCompact[i] = poppedState.inheritedDeferredSetCompact[i]; context->inheritedActionSetCompact[i] = poppedState.inheritedActionSetCompact[i]; } PrtFree(poppedState.inheritedDeferredSetCompact); PrtFree(poppedState.inheritedActionSetCompact); PrtUpdateCurrentActionsSet(context); PrtUpdateCurrentDeferredSet(context); if (isPopStatement) { PrtLog(PRT_STEP_POP, context); } else { // unhandled event PrtLog(PRT_STEP_UNHANDLED, context); } }
PRT_BOOLEAN PrtDequeueEvent( _Inout_ PRT_MACHINEINST_PRIV *context, _Inout_ PRT_FUNSTACK_INFO *frame ) { PRT_UINT32 queueLength; PRT_EVENTQUEUE *queue; PRT_UINT32* deferPacked; PRT_UINT32 i, head; queue = &context->eventQueue; queueLength = queue->eventsSize; deferPacked = PrtGetDeferredPacked(context, context->currentState); head = queue->headIndex; PRT_DBG_ASSERT(queue->size <= queueLength, "Check Failed"); PRT_DBG_ASSERT(queue->size >= 0, "Check Failed"); PRT_DBG_ASSERT(queue->headIndex >= 0, "Check Failed"); PRT_DBG_ASSERT(queue->tailIndex >= 0, "Check Failed"); // // Find the element to dequeue // for (i = 0; i < queue->size; i++) { PRT_UINT32 index = (head + i) % queueLength; PRT_EVENT e = queue->events[index]; PRT_UINT32 triggerIndex = PrtPrimGetEvent(e.trigger); if (context->receive == NULL) { if (!PrtIsEventDeferred(triggerIndex, context->currentDeferredSetCompact)) { PrtFreeValue(context->currentTrigger); PrtFreeValue(context->currentPayload); context->currentTrigger = e.trigger; context->currentPayload = e.payload; break; } } else { if (PrtIsEventReceivable(context, triggerIndex)) { PrtFreeValue(context->currentTrigger); PrtFreeValue(context->currentPayload); context->currentTrigger = e.trigger; context->currentPayload = e.payload; for (PRT_UINT32 i = 0; i < context->receive->nCases; i++) { PRT_CASEDECL *rcase = &context->receive->cases[i]; if (triggerIndex == rcase->triggerEventIndex) { frame->rcase = rcase; PrtPushNewEventHandlerFrame(context, rcase->funIndex, frame->locals); break; } } context->receive = NULL; break; } } } // // Check if not found // if (i == queue->size) { if (context->receive == NULL) { if (PrtStateHasDefaultTransitionOrAction(context)) { PrtFreeValue(context->currentTrigger); PrtFreeValue(context->currentPayload); context->currentTrigger = PrtMkEventValue(PRT_SPECIAL_EVENT_NULL); context->currentPayload = PrtMkNullValue(); return PRT_TRUE; } else { return PRT_FALSE; } } else { PRT_BOOLEAN hasDefaultCase = (context->process->program->eventSets[context->receive->caseSetIndex].packedEvents[0] & 0x1) == 1; if (hasDefaultCase) { PrtFreeValue(context->currentTrigger); PrtFreeValue(context->currentPayload); context->currentTrigger = PrtMkEventValue(PRT_SPECIAL_EVENT_NULL); context->currentPayload = PrtMkNullValue(); for (PRT_UINT32 i = 0; i < context->receive->nCases; i++) { PRT_CASEDECL *rcase = &context->receive->cases[i]; if (PRT_SPECIAL_EVENT_NULL == rcase->triggerEventIndex) { frame->rcase = rcase; PrtPushNewEventHandlerFrame(context, rcase->funIndex, frame->locals); break; } } context->receive = NULL; return PRT_TRUE; } else { return PRT_FALSE; } } } // // Collapse the event queue on the removed event // by moving the previous elements forward. // for (; i > 0; i--) { INT index = (head + i) % queueLength; INT prev = (index - 1 + queueLength) % queueLength; queue->events[index] = queue->events[prev]; } // // Adjust the queue size // queue->headIndex = (queue->headIndex + 1) % queueLength; queue->size--; PRT_DBG_ASSERT(queue->size <= queueLength, "Check Failed"); PRT_DBG_ASSERT(queue->size >= 0, "Check Failed"); PRT_DBG_ASSERT(queue->headIndex >= 0, "Check Failed"); PRT_DBG_ASSERT(queue->tailIndex >= 0, "Check Failed"); // //Log // PrtLog(PRT_STEP_DEQUEUE, context); return PRT_TRUE; }
void PrtRunStateMachine( _Inout_ PRT_MACHINEINST_PRIV *context, _In_ PRT_BOOLEAN doDequeue ) { PRT_BOOLEAN lockHeld; PRT_DODECL *currActionDecl; PRT_UINT32 eventValue; context->isRunning = PRT_TRUE; if (doDequeue) { lockHeld = PRT_TRUE; goto DoDequeue; } else { lockHeld = PRT_FALSE; PrtUnlockMutex(context->stateMachineLock); goto DoEntry; } DoEntry: PrtUpdateCurrentActionsSet(context); PrtUpdateCurrentDeferredSet(context); context->lastOperation = ReturnStatement; if (context->funStack.length == 0) { PrtLog(PRT_STEP_ENTRY, context); PRT_UINT32 entryFunIndex = context->process->program->machines[context->instanceOf].states[context->currentState].entryFunIndex; PrtPushNewEventHandlerFrame(context, entryFunIndex, NULL); } PRT_UINT32 funIndex = PrtBottomOfFunStack(context)->funIndex; context->process->program->machines[context->instanceOf].funs[funIndex].implementation((PRT_MACHINEINST *)context); goto CheckLastOperation; DoAction: currActionDecl = PrtGetAction(context); PRT_UINT32 doFunIndex = currActionDecl->doFunIndex; context->lastOperation = ReturnStatement; if (doFunIndex == PRT_SPECIAL_ACTION_PUSH_OR_IGN) { PrtLog(PRT_STEP_IGNORE, context); } else { if (context->funStack.length == 0) { PrtLog(PRT_STEP_DO, context); PrtPushNewEventHandlerFrame(context, doFunIndex, NULL); } PRT_UINT32 funIndex = PrtBottomOfFunStack(context)->funIndex; context->process->program->machines[context->instanceOf].funs[funIndex].implementation((PRT_MACHINEINST *)context); } goto CheckLastOperation; CheckLastOperation: if (context->receive != NULL) { context->isRunning = PRT_FALSE; PrtUnlockMutex(context->stateMachineLock); return; } switch (context->lastOperation) { case PopStatement: PrtRunExitFunction(context, PrtGetCurrentStateDecl(context)->nTransitions); PrtPopState(context, PRT_TRUE); goto DoDequeue; case RaiseStatement: goto DoHandleEvent; case ReturnStatement: goto DoDequeue; default: PRT_DBG_ASSERT(0, "Unexpected case in switch"); break; } DoDequeue: if (!lockHeld) { lockHeld = PRT_TRUE; PrtLockMutex(context->stateMachineLock); } PrtAssert(context->receive == NULL, "Machine must not be blocked at a receive"); if (PrtDequeueEvent(context, NULL)) { lockHeld = PRT_FALSE; PrtUnlockMutex(context->stateMachineLock); goto DoHandleEvent; } else { context->isRunning = PRT_FALSE; PrtUnlockMutex(context->stateMachineLock); return; } DoHandleEvent: PrtAssert(context->receive == NULL, "Must not be blocked at a receive"); eventValue = PrtPrimGetEvent(PrtGetCurrentTrigger(context)); if (PrtIsPushTransition(context, eventValue)) { PrtTakeTransition(context, eventValue); goto DoEntry; } else if (PrtIsTransitionPresent(context, eventValue)) { PrtRunExitFunction(context, PrtFindTransition(context, eventValue)); PrtTakeTransition(context, eventValue); goto DoEntry; } else if (PrtIsActionInstalled(eventValue, context->currentActionSetCompact)) { goto DoAction; } else { PrtRunExitFunction(context, PrtGetCurrentStateDecl(context)->nTransitions); PrtPopState(context, PRT_FALSE); if (context->isHalted) return; goto DoHandleEvent; } PRT_DBG_ASSERT(PRT_FALSE, "Must not get here"); return; }
void PrtSendPrivate( _Inout_ PRT_MACHINEINST_PRIV *context, _In_ PRT_VALUE *event, _In_ PRT_VALUE *payload ) { PRT_EVENTQUEUE *queue; PRT_UINT32 tail; PRT_UINT32 eventMaxInstances; PRT_UINT32 maxQueueSize; PRT_UINT32 eventIndex; PrtAssert(!PrtIsSpecialEvent(event), "Enqueued event must not be null"); PrtAssert(PrtInhabitsType(payload, PrtGetPayloadType(context, event)), "Payload must be member of event payload type"); if (context->isHalted) { // drop the event silently return; } eventIndex = PrtPrimGetEvent(event); eventMaxInstances = context->process->program->events[eventIndex].eventMaxInstances; maxQueueSize = context->process->program->machines[context->instanceOf].maxQueueSize; PrtLockMutex(context->stateMachineLock); queue = &context->eventQueue; // check if maximum allowed instances of event are already present in queue if (eventMaxInstances != 0xffffffff && PrtIsEventMaxInstanceExceeded(queue, eventIndex, eventMaxInstances)) { PrtUnlockMutex(context->stateMachineLock); PrtHandleError(PRT_STATUS_EVENT_OVERFLOW, context); return; } // if queue is full, resize the queue if possible if (queue->eventsSize == queue->size) { if (maxQueueSize != 0xffffffff && queue->size == maxQueueSize) { PrtUnlockMutex(context->stateMachineLock); PrtHandleError(PRT_STATUS_QUEUE_OVERFLOW, context); return; } PrtResizeEventQueue(context); } tail = queue->tailIndex; // // Add event to the queue // queue->events[tail].trigger = PrtCloneValue(event); queue->events[tail].payload = PrtCloneValue(payload); queue->size++; queue->tailIndex = (tail + 1) % queue->eventsSize; // //Log // PrtLog(PRT_STEP_ENQUEUE, context); // // Now try to run the machine if its not running already // if (context->isRunning) { PrtUnlockMutex(context->stateMachineLock); } else if (context->receive == NULL) { PrtRunStateMachine(context, PRT_TRUE); } else if (PrtIsEventReceivable(context, PrtPrimGetEvent(event))) { PrtRunStateMachine(context, PRT_FALSE); } else { PrtUnlockMutex(context->stateMachineLock); } return; }
PRT_BOOLEAN PrtIsEventMaxInstanceExceeded( _In_ PRT_EVENTQUEUE *queue, _In_ PRT_UINT32 eventIndex, _In_ PRT_UINT32 maxInstances ) { PRT_UINT32 queueSize; PRT_UINT32 head; PRT_UINT32 tail; PRT_UINT16 currMaxInstance; PRT_BOOLEAN isMaxInstancesExceeded; queueSize = queue->eventsSize; head = queue->headIndex; tail = queue->tailIndex; currMaxInstance = 0; isMaxInstancesExceeded = PRT_FALSE; // // head is ahead of tail // if (head > tail) { // // Check from head to end of Array // while (head < queueSize) { if (PrtPrimGetEvent(queue->events[head].trigger) == eventIndex) { currMaxInstance = currMaxInstance + 1; head++; } else { head++; } } // // Reset Head to the start of Array head = 0; } // // Check from start of Array till head // while (head < tail) { if (PrtPrimGetEvent(queue->events[head].trigger) == eventIndex) { currMaxInstance = currMaxInstance + 1; head++; } else { head++; } } if (currMaxInstance >= maxInstances) { isMaxInstancesExceeded = PRT_TRUE; } return isMaxInstancesExceeded; }
FORCEINLINE PRT_DODECL* PrtGetAction( _In_ PRT_MACHINEINST_PRIV *context ) { PRT_UINT32 currEvent = PrtPrimGetEvent(PrtGetCurrentTrigger(context)); PRT_BOOLEAN isActionInstalled = PRT_FALSE; PRT_UINT32 i, nActions; PRT_STATESTACK currStack; PRT_STATEDECL *stateTable; PRT_UINT32 topOfStackState; PRT_STATEDECL *stateDecl; PRT_DODECL *actionDecl = NULL; //check if action is defined for the current state isActionInstalled = PrtIsActionInstalled(currEvent, PrtGetActionsPacked(context, context->currentState)); if (isActionInstalled) { // // get action function // stateDecl = PrtGetCurrentStateDecl(context); nActions = stateDecl->nDos; for (i = 0; i < nActions; i++) { if (stateDecl->dos[i].triggerEventIndex == currEvent) { actionDecl = &stateDecl->dos[i]; return actionDecl; } } } // // Scan the parent states // currStack = context->callStack; stateTable = context->process->program->machines[context->instanceOf].states; for (i = currStack.length - 1; i >= 0; i--) { topOfStackState = currStack.stateStack[i].stateIndex; isActionInstalled = PrtIsActionInstalled(currEvent, PrtGetActionsPacked(context, topOfStackState)); if (isActionInstalled) { // // get action function // nActions = stateTable[topOfStackState].nDos; for (i = 0; i < nActions; i++) { if (stateTable[topOfStackState].dos[i].triggerEventIndex == currEvent) { actionDecl = &stateTable[topOfStackState].dos[i]; return actionDecl; } } } } PRT_DBG_ASSERT(actionDecl != NULL, "Action must not be NULL"); return actionDecl; }
static void PrtUserPrintStep(_In_ PRT_STEP step, PRT_MACHINEINST *sender, _In_ PRT_MACHINEINST *receiver, _In_ PRT_VALUE* event, _In_ PRT_VALUE* payload, _Inout_ char **buffer, _Inout_ PRT_UINT32 *bufferSize, _Inout_ PRT_UINT32 *numCharsWritten) { PRT_MACHINEINST_PRIV * c = (PRT_MACHINEINST_PRIV *)receiver; PRT_STRING machineName = c->process->program->machines[c->instanceOf]->name; PRT_UINT32 machineId = c->id->valueUnion.mid->machineId; PRT_STRING stateName = PrtGetCurrentStateDecl(c)->name; PRT_STRING eventName; switch (step) { case PRT_STEP_HALT: PrtUserPrintString("<HaltLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") halted in state ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_ENQUEUE: eventName = c->process->program->events[PrtPrimGetEvent(event)].name; PrtUserPrintString("<EnqueueLog> Enqueued event ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" with payload ", buffer, bufferSize, numCharsWritten); PrtUserPrintValue(payload, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" on Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(")\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_DEQUEUE: eventName = c->process->program->events[PrtPrimGetEvent(event)].name; PrtUserPrintString("<DequeueLog> Dequeued event ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" with payload ", buffer, bufferSize, numCharsWritten); PrtUserPrintValue(payload, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" by Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(")\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_ENTRY: PrtUserPrintString("<StateLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") entered state ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_CREATE: PrtUserPrintString("<CreateLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") is created\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_GOTO: { PRT_MACHINEINST_PRIV *context = (PRT_MACHINEINST_PRIV *)sender; PRT_STRING destStateName = c->process->program->machines[context->instanceOf]->states[context->destStateIndex].name; PrtUserPrintString("<GotoLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") goes to state ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(destStateName, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" with payload ", buffer, bufferSize, numCharsWritten); PrtUserPrintValue(payload, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; } case PRT_STEP_RAISE: eventName = c->process->program->events[PrtPrimGetEvent(event)].name; PrtUserPrintString("<RaiseLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") raised event ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" with payload ", buffer, bufferSize, numCharsWritten); PrtUserPrintValue(payload, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_POP: PrtUserPrintString("<PopLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") popped and reentered state ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_PUSH: PrtUserPrintString("<PushLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") pushed\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_UNHANDLED: eventName = c->process->program->events[c->eventValue].name; PrtUserPrintString("<PopLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") popped with unhandled event ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" and reentered state ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_DO: PrtUserPrintString("<ActionLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") executed action in state ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_EXIT: PrtUserPrintString("<ExitLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") exiting state ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; case PRT_STEP_IGNORE: eventName = c->process->program->events[PrtPrimGetEvent(event)].name; PrtUserPrintString("<ActionLog> Machine ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(machineName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(machineId, buffer, bufferSize, numCharsWritten); PrtUserPrintString(") ignored event ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(eventName, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" in state ", buffer, bufferSize, numCharsWritten); PrtUserPrintString(stateName, buffer, bufferSize, numCharsWritten); PrtUserPrintString("\n", buffer, bufferSize, numCharsWritten); break; default: PrtAssert(PRT_FALSE, "Illegal PRT_STEP value"); break; } }
static void PrtUserPrintValue(_In_ PRT_VALUE *value, _Inout_ char **buffer, _Inout_ PRT_UINT32 *bufferSize, _Inout_ PRT_UINT32 *numCharsWritten) { PRT_STRING frgnStr; PRT_VALUE_KIND kind = value->discriminator; switch (kind) { case PRT_VALUE_KIND_NULL: PrtUserPrintString("null", buffer, bufferSize, numCharsWritten); break; case PRT_VALUE_KIND_BOOL: PrtUserPrintString(PrtPrimGetBool(value) == PRT_TRUE ? "true" : "false", buffer, bufferSize, numCharsWritten); break; case PRT_VALUE_KIND_INT: PrtUserPrintInt32(PrtPrimGetInt(value), buffer, bufferSize, numCharsWritten); break; case PRT_VALUE_KIND_EVENT: PrtUserPrintString("<", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(PrtPrimGetEvent(value), buffer, bufferSize, numCharsWritten); PrtUserPrintString(">", buffer, bufferSize, numCharsWritten); break; case PRT_VALUE_KIND_MID: PrtUserPrintMachineId(PrtPrimGetMachine(value), buffer, bufferSize, numCharsWritten); break; case PRT_VALUE_KIND_FORGN: frgnStr = prtForeignTypeDecls[value->valueUnion.frgn->typeTag].toStringFun(value->valueUnion.frgn->value); PrtUserPrintString(frgnStr, buffer, bufferSize, numCharsWritten); PrtFree(frgnStr); break; case PRT_VALUE_KIND_MAP: { PRT_MAPVALUE *mval = value->valueUnion.map; PRT_MAPNODE *next = mval->first; PrtUserPrintString("{", buffer, bufferSize, numCharsWritten); while (next != NULL) { PrtUserPrintValue(next->key, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" --> ", buffer, bufferSize, numCharsWritten); PrtUserPrintValue(next->value, buffer, bufferSize, numCharsWritten); if (next->bucketNext != NULL) { PrtUserPrintString("*", buffer, bufferSize, numCharsWritten); } if (next->insertNext != NULL) { PrtUserPrintString(", ", buffer, bufferSize, numCharsWritten); } next = next->insertNext; } PrtUserPrintString("} (", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(mval->size, buffer, bufferSize, numCharsWritten); PrtUserPrintString(" / ", buffer, bufferSize, numCharsWritten); PrtUserPrintUint32(PrtMapCapacity(value), buffer, bufferSize, numCharsWritten); PrtUserPrintString(")", buffer, bufferSize, numCharsWritten); break; } case PRT_VALUE_KIND_SEQ: { PRT_UINT32 i; PRT_SEQVALUE *sVal = value->valueUnion.seq; PrtUserPrintString("[", buffer, bufferSize, numCharsWritten); for (i = 0; i < sVal->size; ++i) { PrtUserPrintValue(sVal->values[i], buffer, bufferSize, numCharsWritten); if (i < sVal->size - 1) { PrtUserPrintString(", ", buffer, bufferSize, numCharsWritten); } } PrtUserPrintString("]", buffer, bufferSize, numCharsWritten); break; } case PRT_VALUE_KIND_TUPLE: { PRT_UINT32 i; PRT_TUPVALUE *tval = value->valueUnion.tuple; PrtUserPrintString("(", buffer, bufferSize, numCharsWritten); if (tval->size == 1) { PrtUserPrintValue(tval->values[0], buffer, bufferSize, numCharsWritten); PrtUserPrintString(",)", buffer, bufferSize, numCharsWritten); } else { for (i = 0; i < tval->size; ++i) { PrtUserPrintValue(tval->values[i], buffer, bufferSize, numCharsWritten); if (i < tval->size - 1) { PrtUserPrintString(", ", buffer, bufferSize, numCharsWritten); } else { PrtUserPrintString(")", buffer, bufferSize, numCharsWritten); } } } break; } default: PrtAssert(PRT_FALSE, "PrtUserPrintValue: Invalid value"); break; } }