public void Announce(PrtEventValue ev, PrtValue payload, PrtMachine parent) { if (ev.Equals(PrtValue.@null)) { throw new PrtIllegalEnqueueException("Enqueued event must not be null"); } PrtType prtType = ev.evt.payloadType; //assertion to check if argument passed inhabits the payload type. if (prtType is PrtNullType) { if (!payload.Equals(PrtValue.@null)) { throw new PrtIllegalEnqueueException("Did not expect a payload value"); } } else if (!PrtValue.PrtInhabitsType(payload, prtType)) { throw new PrtInhabitsTypeException(String.Format("Payload <{0}> does not match the expected type <{1}> with event <{2}>", payload.ToString(), prtType.ToString(), ev.evt.name)); } var allSpecMachines = GetSpecMachines(parent.renamedName); foreach (var mon in allSpecMachines) { if (mon.observes.Contains(ev)) { TraceLine("<AnnounceLog> Enqueued Event <{0}, {1}> to Spec Machine {2}", ev, payload, mon.Name); mon.PrtEnqueueEvent(ev, payload, parent); } } }
public bool PrtPopState(bool isPopStatement) { Debug.Assert(stateStack.TopOfStack != null); //pop stack stateStack.PopStackFrame(); if (stateStack.TopOfStack == null) { if (isPopStatement) { throw new PrtInvalidPopStatement(); } //TODO : Handle the spec machine case separately for the halt event else if (!eventValue.Equals(PrtValue.halt)) { throw new PrtUnhandledEventException(string.Format("{0} failed to handle {1}", Name, eventValue.ToString())); } else { stateImpl.TraceLine("<HaltLog> Machine {0}-{1} HALTED", this.Name, this.instanceNumber); currentStatus = PrtMachineStatus.Halted; } } return(currentStatus == PrtMachineStatus.Halted); }
public bool PrtPopState(bool isPopStatement) { Debug.Assert(stateStack.TopOfStack != null); //pop stack stateStack.PopStackFrame(); if (stateStack.TopOfStack == null) { if (isPopStatement) { throw new PrtInvalidPopStatement(); } //TODO : Handle the spec machine case separately for the halt event else if (!eventValue.Equals(PrtValue.halt)) { throw new PrtUnhandledEventException(string.Format("{0} failed to handle event {1}", Name, eventValue.ToString())); } else { if (this as PrtImplMachine != null) { stateImpl.TraceLine("<HaltLog> Machine {0}-{1} HALTED with {2} events in the queue", this.Name, this.instanceNumber, (((PrtImplMachine)this).eventQueue).Size()); } else { //SpecMachine case: //TODO: is it possible to send "halt" event to a spec machine? stateImpl.TraceLine("<HaltLog> Machine {0}-{1} HALTED", this.Name, this.instanceNumber); } currentStatus = PrtMachineStatus.Halted; } } return(currentStatus == PrtMachineStatus.Halted); }
public override bool Equals(object obj) { var mapKey = obj as PrtMapKey; if (mapKey == null) { return(false); } return(key.Equals(mapKey.key)); }
public override void PrtEnqueueEvent(PrtValue e, PrtValue arg, PrtMachine source, PrtMachineValue target = null) { PrtEventValue ev = e as PrtEventValue; if (ev.evt.name == "null") { throw new PrtIllegalEnqueueException("Enqueued event must not be null"); } //check if the sent event is in source send set if (!source.sends.Contains(e as PrtEventValue)) { throw new PrtIllegalEnqueueException(String.Format("Machine <0> cannot send event {1}", source.Name, e.ToString())); } //check if the sent event is in target permissions if (target is PrtInterfaceValue) { if (!(target as PrtInterfaceValue).permissions.Contains(e as PrtEventValue)) { throw new PrtIllegalEnqueueException(String.Format("Event {1} is not in the permission set of the target", e.ToString())); } } PrtType prtType = ev.evt.payloadType; //assertion to check if argument passed inhabits the payload type. if (prtType is PrtNullType) { if (!arg.Equals(PrtValue.@null)) { throw new PrtIllegalEnqueueException("Did not expect a payload value"); } } else if (!PrtValue.PrtInhabitsType(arg, prtType)) { throw new PrtInhabitsTypeException(String.Format("Payload <{0}> does not match the expected type <{1}> with event <{2}>", arg.ToString(), prtType.ToString(), ev.evt.name)); } //check if the event sent is in the permissions if (currentStatus == PrtMachineStatus.Halted) { stateImpl.Trace( @"<EnqueueLog> {0}-{1} Machine has been halted and Event {2} is dropped", this.Name, this.instanceNumber, ev.evt.name); } else { stateImpl.Trace( @"<EnqueueLog> Enqueued Event <{0}, {1}> in {2}-{3} by {4}-{5}", ev.evt.name, arg.ToString(), this.Name, this.instanceNumber, source.Name, source.instanceNumber); this.eventQueue.EnqueueEvent(e, arg); if (this.maxBufferSize != DefaultMaxBufferSize && this.eventQueue.Size() > this.maxBufferSize) { if (this.doAssume) { throw new PrtAssumeFailureException(); } else { throw new PrtMaxBufferSizeExceededException( String.Format(@"<EXCEPTION> Event Buffer Size Exceeded {0} in Machine {1}-{2}", this.maxBufferSize, this.Name, this.instanceNumber)); } } if (currentStatus == PrtMachineStatus.Blocked && this.eventQueue.IsEnabled(this)) { currentStatus = PrtMachineStatus.Enabled; } } //Announce it to all the spec machines stateImpl.Announce(e as PrtEventValue, arg, source); }
//public abstract bool Equals(PrtValue val); public static bool PrtInhabitsType(PrtValue value, PrtType type) { if (type is PrtAnyType) { return(true); } else if (value.Equals(@null)) { return(type is PrtNullType || type is PrtEventType || type is PrtMachineType); } else if (type is PrtEnumType) { PrtEnumType enumType = type as PrtEnumType; PrtIntValue intValue = value as PrtIntValue; if (intValue == null) { return(false); } return(enumType.enumConstants.ContainsKey(intValue.nt)); } else if (type is PrtIntType) { return(value is PrtIntValue); } else if (type is PrtFloatType) { return(value is PrtFloatValue); } else if (type is PrtBoolType) { return(value is PrtBoolValue); } else if (type is PrtEventType) { return(value is PrtEventValue); } else if (type is PrtMachineType) { return(value is PrtMachineValue || value is PrtInterfaceValue); } else if (type is PrtInterfaceType) { var interValue = value as PrtInterfaceValue; if (interValue == null) { return(false); } else { if (interValue.permissions == null) { return((type as PrtInterfaceType).permissions == null); } else { if ((type as PrtInterfaceType).permissions == null) { return(false); } } if (interValue.permissions.Count() != (type as PrtInterfaceType).permissions.Count()) { return(false); } else { foreach (var ev in interValue.permissions) { if (!(type as PrtInterfaceType).permissions.Contains(ev)) { return(false); } } return(true); } } } else if (type is PrtNamedTupleType) // must come before PrtTupleType since PrtNamedTupleType derives from PrtTupleType { var nmtupType = type as PrtNamedTupleType; var nmtupVal = value as PrtNamedTupleValue; if (nmtupVal == null) { return(false); } if (nmtupVal.fieldValues.Count != nmtupType.fieldTypes.Count) { return(false); } for (int i = 0; i < nmtupVal.fieldValues.Count; i++) { if (nmtupVal.fieldNames[i] != nmtupType.fieldNames[i]) { return(false); } } for (int i = 0; i < nmtupVal.fieldValues.Count; i++) { if (!PrtInhabitsType(nmtupVal.fieldValues[i], nmtupType.fieldTypes[i])) { return(false); } } return(true); } else if (type is PrtTupleType) { var tupType = type as PrtTupleType; var tupVal = value as PrtTupleValue; if (tupVal == null) { return(false); } if (tupVal.fieldValues.Count != tupType.fieldTypes.Count) { return(false); } for (int i = 0; i < tupVal.fieldValues.Count; i++) { if (!PrtInhabitsType(tupVal.fieldValues[i], tupType.fieldTypes[i])) { return(false); } } return(true); } else if (type is PrtMapType) { var mapType = type as PrtMapType; var mapVal = value as PrtMapValue; if (mapVal == null) { return(false); } foreach (var p in mapVal.keyToValueMap) { if (!PrtInhabitsType(p.Key.key, mapType.keyType)) { return(false); } if (!PrtInhabitsType(p.Value, mapType.valType)) { return(false); } } return(true); } else if (type is PrtSeqType) { var seqType = type as PrtSeqType; var seqVal = value as PrtSeqValue; if (seqVal == null) { return(false); } foreach (var elem in seqVal.elements) { if (!PrtInhabitsType(elem, seqType.elemType)) { return(false); } } return(true); } else { throw new PrtInternalException("Unknown type in PrtInhabitsType"); } }
public override void PrtEnqueueEvent(PrtValue e, PrtValue arg, PrtMachine source, PrtMachineValue target = null) { int numOfStepsTaken = 0; // set the currentTrigger and currentPayload fields // so that we can reuse the common functions currentPayload = arg.Clone(); currentTrigger = e; PrtValue currEventValue; PrtFun currAction; bool hasMoreWork = false; try { Start: switch (nextSMOperation) { case PrtNextStatemachineOperation.ExecuteFunctionOperation: goto DoExecuteFunction; case PrtNextStatemachineOperation.HandleEventOperation: goto DoHandleEvent; } DoExecuteFunction: if (invertedFunStack.TopOfStack == null) { //Trace: entered state PrtFun entryFun = CurrentState.entryFun; if (entryFun.IsAnonFun) { PrtPushFunStackFrame(entryFun, entryFun.CreateLocals(currentPayload)); } else { PrtPushFunStackFrame(entryFun, entryFun.CreateLocals()); } } //invoke the function invertedFunStack.TopOfStack.fun.Execute(stateImpl, this); goto CheckFunLastOperation; DoAction: currAction = PrtFindActionHandler(eventValue); if (currAction == PrtFun.IgnoreFun) { //Trace: Performed ignore action for the event currentTrigger = PrtValue.@null; currentPayload = PrtValue.@null; } else { if (invertedFunStack.TopOfStack == null) { //Trace: executed the action handler for event if (currAction.IsAnonFun) { PrtPushFunStackFrame(currAction, currAction.CreateLocals(currentPayload)); } else { PrtPushFunStackFrame(currAction, currAction.CreateLocals()); } } //invoke the action handler invertedFunStack.TopOfStack.fun.Execute(stateImpl, this); } goto CheckFunLastOperation; CheckFunLastOperation: switch (continuation.reason) { case PrtContinuationReason.Goto: { stateExitReason = PrtStateExitReason.OnGotoStatement; nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation; PrtPushExitFunction(); goto DoExecuteFunction; } case PrtContinuationReason.Raise: { nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation; hasMoreWork = true; goto Finish; } case PrtContinuationReason.Return: { switch (stateExitReason) { case PrtStateExitReason.NotExit: { nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation; hasMoreWork = false; goto Finish; } case PrtStateExitReason.OnGotoStatement: { PrtChangeState(destOfGoto); currentTemperature = destOfGoto.temperature; nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation; stateExitReason = PrtStateExitReason.NotExit; hasMoreWork = true; goto Finish; } case PrtStateExitReason.OnUnhandledEvent: { hasMoreWork = !PrtPopState(false); nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation; stateExitReason = PrtStateExitReason.NotExit; goto Finish; } case PrtStateExitReason.OnTransition: { stateExitReason = PrtStateExitReason.OnTransitionAfterExit; nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation; PrtPushTransitionFun(eventValue); goto DoExecuteFunction; } case PrtStateExitReason.OnTransitionAfterExit: { // The parameter to an anonymous transition function is always passed as swap. // Update currentPayload to the latest value of the parameter so that the correct // value gets passed to the entry function of the target state. PrtTransition transition = CurrentState.transitions[eventValue]; PrtFun transitionFun = transition.transitionFun; if (transitionFun.IsAnonFun) { currentPayload = continuation.retLocals[0]; } PrtChangeState(transition.gotoState); currentTemperature = transition.gotoState.temperature; hasMoreWork = true; nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation; stateExitReason = PrtStateExitReason.NotExit; goto Finish; } default: { Debug.Assert(false, "Unexpected value for exit reason"); goto Finish; } } } default: { Debug.Assert(false, "Unexpected value for continuation reason"); goto Finish; } } DoHandleEvent: if (!currentTrigger.Equals(PrtValue.@null)) { currEventValue = currentTrigger; currentTrigger = PrtValue.@null; } else { currEventValue = eventValue; } if (PrtIsTransitionPresent(currEventValue)) { stateExitReason = PrtStateExitReason.OnTransition; nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation; eventValue = currEventValue; PrtPushExitFunction(); goto DoExecuteFunction; } else if (PrtIsActionInstalled(currEventValue)) { eventValue = currEventValue; goto DoAction; } else { stateExitReason = PrtStateExitReason.OnUnhandledEvent; nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation; eventValue = currEventValue; PrtPushExitFunction(); goto DoExecuteFunction; } Finish: if (hasMoreWork) { if (numOfStepsTaken > 100000) { throw new PrtInfiniteRaiseLoop("Infinite loop in spec machine"); } else { numOfStepsTaken++; goto Start; } } else { return; } } catch (PrtException ex) { stateImpl.Exception = ex; } }