using System;
using System.Collections.Generic;
namespace Ariadne.UnitTests
{
///
/// The context the trigger wait scripts run in, with the triggers they wait on and a log they write to.
///
public class TriggerWorld
{
public readonly Trigger Door = new Trigger();
public readonly Trigger Alarm = new Trigger();
[Scratch]
public readonly List Log = new List();
}
///
/// Waits for the door, then logs.
///
public partial class SingleTriggerScript : Arc
{
protected override void Run(TriggerWorld world)
{
world.Log.Add("start");
first:
Wait(world.Door);
world.Log.Add("door");
}
}
///
/// Waits for the door, then for the alarm.
///
public partial class TwoWaitsScript : Arc
{
protected override void Run(TriggerWorld world)
{
first:
Wait(world.Door);
world.Log.Add("door");
second:
Wait(world.Alarm);
world.Log.Add("alarm");
}
}
///
/// Waits for either trigger, and logs which one it was.
///
public partial class AnyTriggerScript : Arc
{
protected override void Run(TriggerWorld world)
{
first:
Trigger fired = WaitAny(world.Door, world.Alarm);
world.Log.Add(fired == world.Alarm ? "alarm" : "door");
}
}
///
/// Waits for both triggers, and logs which one came last.
///
public partial class AllTriggersScript : Arc
{
protected override void Run(TriggerWorld world)
{
first:
Trigger last = WaitAll(world.Door, world.Alarm);
world.Log.Add(last == world.Alarm ? "alarm last" : "door last");
}
}
///
/// Waits for the same trigger twice in one wait.
///
public partial class RepeatedTriggerScript : Arc
{
protected override void Run(TriggerWorld world)
{
first:
WaitAll(world.Door, world.Door);
world.Log.Add("through");
}
}
///
/// Waits for the door three times, with a local counting the trips.
///
public partial class LoopedTriggerScript : Arc
{
protected override void Run(TriggerWorld world)
{
int count = 0;
while (count < 3)
{
spin:
Wait(world.Door);
++count;
world.Log.Add("door " + count);
}
}
}
///
/// Waits for the door unless told to skip it, and then sleeps, so a restart can send it past the wait.
///
public partial class RestartableTriggerScript : Arc
{
public bool Skip;
protected override void Run(TriggerWorld world)
{
if (!Skip)
{
first:
Wait(world.Door);
world.Log.Add("door");
}
nap:
Wait(TimeSpan.FromSeconds(100));
world.Log.Add("rested");
}
}
///
/// Takes the trigger a wait ended on into a local it declared earlier, and into a field.
///
public partial class AssignedTriggerScript : Arc
{
public Trigger Last;
protected override void Run(TriggerWorld world)
{
Trigger first = null;
pick:
first = WaitAny(world.Door, world.Alarm);
again:
Last = WaitAny(world.Door, world.Alarm);
world.Log.Add(first == world.Door ? "first door" : "first alarm");
world.Log.Add(Last == world.Door ? "then door" : "then alarm");
}
}
///
/// Keeps the trigger a wait ended on across a later pause.
///
public partial class KeptTriggerScript : Arc
{
protected override void Run(TriggerWorld world)
{
first:
Trigger fired = WaitAny(world.Door, world.Alarm);
second:
Yield();
world.Log.Add(fired == world.Alarm ? "alarm" : "door");
}
}
///
/// Waits in a passage that hands the trigger back.
///
public partial class PassageTriggerScript : Arc
{
private Trigger Pick(TriggerWorld world)
{
inner:
return WaitAny(world.Door, world.Alarm);
}
protected override void Run(TriggerWorld world)
{
outer:
Trigger picked = Pick(world);
world.Log.Add(picked == world.Alarm ? "alarm" : "door");
}
}
///
/// Offers a passage for other arcs to run, which waits for the door.
///
public partial class TriggerLookoutScript : Arc
{
public void Watch(TriggerWorld world)
{
watch:
Wait(world.Door);
world.Log.Add("seen");
}
protected override void Run(TriggerWorld world)
{
}
}
///
/// Runs the passage of another arc that waits for the door.
///
public partial class TriggerRelayScript : Arc
{
public TriggerLookoutScript Lookout;
protected override void Run(TriggerWorld world)
{
relay:
Lookout.Watch(world);
world.Log.Add("relayed");
}
}
///
/// Waits in a generic passage, which keeps its locals in a frame of its own.
///
public partial class GenericTriggerScript : Arc
{
private Trigger Choose(TriggerWorld world, ItemType marker)
{
inner:
return WaitAny(world.Door, world.Alarm);
}
protected override void Run(TriggerWorld world)
{
outer:
Trigger picked = Choose(world, 5);
world.Log.Add(picked == world.Alarm ? "alarm" : "door");
}
}
///
/// Waits for the door with a time limit, and logs whether it came.
///
public partial class TimedDoorScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
protected override void Run(TriggerWorld world)
{
first:
Trigger got = Wait(world.Door, timeout: Limit);
world.Log.Add(got == null ? "timed out" : "door");
}
}
///
/// Waits for either trigger with a time limit, and logs which one came.
///
public partial class TimedAnyScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
protected override void Run(TriggerWorld world)
{
first:
Trigger fired = WaitAny(timeout: Limit, world.Door, world.Alarm);
world.Log.Add(fired == null ? "timed out" : fired == world.Alarm ? "alarm" : "door");
}
}
///
/// Waits for both triggers with a time limit, and logs which one came last.
///
public partial class TimedAllScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
protected override void Run(TriggerWorld world)
{
first:
Trigger last = WaitAll(timeout: Limit, world.Door, world.Alarm);
world.Log.Add(last == null ? "timed out" : last == world.Alarm ? "alarm last" : "door last");
}
}
///
/// Waits for the door with a time limit, and then sleeps for a long time.
///
public partial class TimedThenNapScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
protected override void Run(TriggerWorld world)
{
first:
Wait(world.Door, timeout: Limit);
world.Log.Add("waited");
second:
Wait(TimeSpan.FromSeconds(100));
world.Log.Add("rested");
}
}
///
/// Waits for the door with a time limit three times, with the arguments named out of order.
///
public partial class TimedLoopScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
protected override void Run(TriggerWorld world)
{
int count = 0;
while (count < 3)
{
spin:
Trigger got = Wait(timeout: Limit, trigger: world.Door);
++count;
world.Log.Add((got == null ? "timed out " : "door ") + count);
}
}
}
///
/// Waits for either trigger with a time limit in a passage that hands the trigger back.
///
public partial class TimedPassageScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
private Trigger Pick(TriggerWorld world)
{
inner:
return WaitAny(timeout: Limit, world.Door, world.Alarm);
}
protected override void Run(TriggerWorld world)
{
outer:
Trigger picked = Pick(world);
world.Log.Add(picked == null ? "timed out" : picked == world.Alarm ? "alarm" : "door");
}
}
///
/// Waits for the door with a time limit, ignoring the result.
///
public partial class TimedDiscardScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
protected override void Run(TriggerWorld world)
{
first:
Wait(world.Door, timeout: Limit);
world.Log.Add("through");
}
}
///
/// Waits for the door inside a branch and a loop that is only sometimes taken.
///
public partial class BranchingTriggerScript : Arc
{
public bool Skip;
protected override void Run(TriggerWorld world)
{
if (!Skip)
{
inside:
Wait(world.Door);
world.Log.Add("waited");
}
world.Log.Add("done");
}
}
}