public void CreateTrigger(StateMachine sm) { if (null != Condition) { var trigger = new Trigger(Event, Condition); trigger.AddEffects(Effects); sm.AddTrigger(trigger); } else if(Effects.Any()) { var trigger = new Trigger(Event, new AnyCondition()); trigger.AddEffects(Effects); sm.AddTrigger(trigger); } }
private void ValidateTrigger(Trigger trigger) { var tset = trigger.Transitions; foreach (var v in tset.Variables) { var branches = new List<IGate>(); foreach(var t in tset.GetTransitions(v)) { var c = t.PreCondition; // preconditions must not intersect foreach(var b in branches) { var sum = Gate.ComposeAND(c, b); if(!(sum is FalseGate)) { } } branches.Add(c); } } var tlist = new List<Trigger>(); }
/// <summary> /// Adds a trigger to the state machine. /// </summary> /// <param name="trigger">The trigger object to add.</param> public void AddTrigger(Trigger trigger) { var e = trigger.Event; SetModify(); try { TraceDependencies("add trigger '{0}' ...", trigger.Name); // ValidateTrigger(trigger); var tlist = new List<ProductTrigger>(); // examinate the precondition ... var precondition = trigger.PreCondition; if (precondition.Type == GateType.Fixed) { // constant if (precondition is FalseGate) { Trace("SMG033: warning: trigger '{0}' precondition is never met.", trigger); } else if (precondition is TrueGate) { Trace("SMG034: warning: trigger '{0}' precondition is always true.", trigger); tlist.Add(new ProductTrigger(trigger)); } } else if (precondition.Type == GateType.OR) { // OR combination, split into multiple simple triggers var inputs = precondition.GetInputs(); TraceDependencies("split trigger [{0}] into its branches ...", inputs.ToSeparatorList()); // analyze conditions // TraceDependencies("{0}", trigger.Transitions.ToDebugString()); // split into multiple triggers foreach (var product in inputs) { // extract the transition subset for the guard condition var tset = new TransitionSet(trigger.Transitions, product); TraceDependencies(" transition set of branch [{0}]: {1}", product, tset.ToDebugString()); var pre = ReplaceVariableCondition(tset, product, false); var post = ReplaceVariableCondition(tset, product, true); TraceDependencies(" branch conditions [{0} => {1}].", pre, post); // add branch trigger tlist.Add(new ProductTrigger(trigger, tset, pre, post)); } } else { // add original trigger tlist.Add(new ProductTrigger(trigger)); } // process resulting triggers foreach (var t1 in tlist) { TraceDependencies("product trigger {0} ...", t1); TraceDependencies(" conditions [{0}, {1}] ...", t1.PreCondition, t1.PostCondition); TraceDependencies(" transitions {0}", trigger.Transitions.ToDebugString()); t1.Qualify(); // check if any existing trigger is conflicting foreach (var existingtrigger in e.Triggers) { // the new trigger precondition must not intersect any existing precondition var product = Gate.ComposeAND(existingtrigger.PreCondition, t1.PreCondition); product = ReplaceTransitionVariables(existingtrigger.Transitions, product, false); if (!product.IsFalse()) { throw new CompilerException(ErrorCode.AmbigousPreCondition, "ambigous transition conditions [" + existingtrigger.PreCondition + ", " + t1.PreCondition + "]."); } } e.Triggers.Add(t1); } } catch(CompilerException ex) { AddError(ex); } }
internal void AddTrigger(Trigger t) { _triggers.Add(t); }
/// <summary> /// Creates a trigger based on another trigger, with new conditions. /// </summary> /// <param name="parent">The original trigger.</param> /// <param name="tset">The corresponding transition set.</param> /// <param name="pre">The precondition for the new trigger.</param> /// <param name="post">The postcondition for the new trigger.</param> protected Trigger(Trigger parent, TransitionSet tset, IGate pre, IGate post) : base(tset, pre, post) { Event = parent.Event; AddEffects(parent.Effects); }
/// <summary> /// Creates a trigger based on another trigger, with new conditions. /// </summary> /// <param name="parent">The original trigger.</param> /// <param name="tset">The corresponding transition set.</param> /// <param name="pre">The precondition for the new trigger.</param> /// <param name="post">The postcondition for the new trigger.</param> internal ProductTrigger(Trigger parent, TransitionSet tset, IGate pre, IGate post) : base(parent, tset, pre, post) { }
public ProductTrigger(Trigger parent) : base(parent, parent.Transitions, parent.PreCondition, parent.PostCondition) { }
public void SMG_05_01_CodeGeneration() { var cc = new StateMachineCompiler(); cc.CompileString(ReadEmbeddedScript("CodeGeneration.smg")); cc.GenerateCode(); Assert.AreEqual(2, cc.SM.Events.Count()); var u = cc.SM.AddEvent("u"); var trigger = new Trigger(u, cc.EvaluateCondition("s(b => a)")); trigger.AddEffects(new[] { new CallEffect(cc.SM, "m") }); cc.SM.AddTrigger(trigger); Assert.IsFalse(cc.SM.IsPrepared); cc.Parameters.IsProcessEventPublic = true; cc.GenerateCode(); Assert.IsTrue(cc.SM.IsPrepared); Assert.AreEqual(3, cc.SM.Events.Count()); Trace("output:\n{0}", cc.Output); var csharp = new CSharpCodeProvider(); var options = new CompilerParameters(); var result = csharp.CompileAssemblyFromSource(options, cc.Output); if (result.Errors.Count > 0) { foreach (var e in result.Errors) { Trace("{0}", e); } Assert.Fail("generated code failed to compile."); } var dll = result.CompiledAssembly; var type = dll.GetType("CodeGeneration"); var eventtype = dll.GetType("EventCode"); var events = Enum.GetValues(eventtype); var x = Activator.CreateInstance(type); var tostatestring = type.GetMethod("ToStateString"); Trace("initial state [{0}].", tostatestring.Invoke(x, new object[0])); var processevent = type.GetMethod("ProcessEvent"); var sendevent = events.GetValue(0); Trace("sending event '{0}' ...", sendevent); processevent.Invoke(x, new object[] { sendevent }); var statestring = tostatestring.Invoke(x, new object[0]).ToString(); Trace("state after [{0}].", statestring); Assert.AreEqual("s(b) t(b) f(0)", statestring); sendevent = events.GetValue(1); Trace("sending event '{0}' ...", sendevent); processevent.Invoke(x, new object[] { sendevent }); statestring = tostatestring.Invoke(x, new object[0]).ToString(); Trace("state after [{0}].", statestring); Assert.AreEqual("s(b) t(a) f(1)", statestring); }
public void SMG_03_StateCondition() { TraceFlags.ShowDepencencyAnalysis = true; var sm = new StateMachine(); var stype = new SimpleStateType("State"); stype.AddStateNames(new[] { "A", "B", "C" }); var s = sm.AddVariable("s", stype); var t = sm.AddVariable("t", stype); var c = new StateCondition(s); c.SetPreStates("A,B"); c.SetPostStates("C"); var e1 = sm.AddEvent("e1"); var trigger = new Trigger(e1, c); sm.AddTrigger(trigger); var gc1 = new StateCondition(s); gc1.SetPreStates("A"); // gc1.SetPostStates("C"); sm.AddGuard(gc1, GuardType.LEAVE, "g1"); var gc2 = new StateCondition(s); gc2.SetPreStates("C"); sm.AddGuard(gc2, GuardType.ENTER, "g2"); { var c1 = new StateCondition(t); c1.SetPreStates("A"); var c2 = new StateCondition(s); c2.SetPreStates("A"); } sm.Calculate(); // sm.Dump(); var e = sm.Events.First(); Assert.AreEqual("e1", e.Name); Assert.AreEqual(2, e.Triggers.Count); var t1 = e.Triggers[0]; var t2 = e.Triggers[1]; Assert.AreEqual(2, t1.Guards.Count); Assert.AreEqual(1, t2.Guards.Count); Assert.IsTrue(t1.Guards.Any(g => g.Name == "g1")); Assert.IsTrue(t1.Guards.Any(g => g.Name == "g2")); Assert.IsTrue(t2.Guards.Any(g => g.Name == "g2")); }