namespace Ariadne.UnitTests
{
///
/// Calls its own passage until three levels deep, with a local at each level that is used after the pause.
///
public partial class Countdown : Arc
{
public string Log = "";
private void Descend(ArcTests.Gates gates, int level)
{
int mine = level * 10;
wait:
while (!gates.Open.Contains("go" + level))
{
Yield();
}
if (level < 3)
{
deeper:
Descend(gates, level + 1);
}
Log += mine + ";";
}
protected override void Run(ArcTests.Gates gates)
{
start:
Descend(gates, 1);
}
}
///
/// Has two passages that call each other, each pausing at every level.
///
public partial class Rally : Arc
{
public string Log = "";
private void Ping(ArcTests.Gates gates, int left)
{
wait:
while (!gates.Open.Contains("ping" + left))
{
Yield();
}
Log += "ping" + left + ";";
if (left > 0)
{
back:
Pong(gates, left - 1);
}
}
private void Pong(ArcTests.Gates gates, int left)
{
wait:
while (!gates.Open.Contains("pong" + left))
{
Yield();
}
Log += "pong" + left + ";";
if (left > 0)
{
again:
Ping(gates, left - 1);
}
}
protected override void Run(ArcTests.Gates gates)
{
start:
Ping(gates, 3);
}
}
///
/// Has a generic passage that calls itself with the type arguments it was given.
///
public partial class Layering : Arc
{
public string Log = "";
private void Stack(ArcTests.Gates gates, X item, int left)
{
X kept = item;
wait:
while (!gates.Open.Contains("layer" + left))
{
Yield();
}
if (left > 0)
{
deeper:
Stack(gates, kept, left - 1);
}
Log += kept + "@" + left + ";";
}
protected override void Run(ArcTests.Gates gates)
{
start:
Stack(gates, "box", 2);
}
}
///
/// Has a generic passage that calls itself with its two type arguments swapped, so its frames alternate between
/// two types.
///
public partial class Trading : Arc
{
public string Log = "";
private void Swap(ArcTests.Gates gates, X first, Y second, int left)
{
X kept = first;
Y other = second;
wait:
while (!gates.Open.Contains("trade" + left))
{
Yield();
}
Log += kept + "/" + other + ";";
if (left > 0)
{
deeper:
Swap(gates, other, kept, left - 1);
}
}
protected override void Run(ArcTests.Gates gates)
{
start:
Swap(gates, 1, "one", 2);
}
}
///
/// Runs a passage that two arcs of this class hand to each other, so each serve is run on the other arc.
///
public partial class Volley : Arc
{
public Volley Partner;
public string Log = "";
public void Serve(ArcTests.Gates gates, int shot)
{
int mine = shot;
wait:
while (!gates.Open.Contains("hit" + shot))
{
Yield();
}
Log += "serve" + mine + ";";
if (shot > 1)
{
back:
Partner.Serve(gates, shot - 1);
}
}
protected override void Run(ArcTests.Gates gates)
{
start:
Serve(gates, 3);
}
}
///
/// Offers a passage that calls itself, for other arcs to run.
///
public partial class Orchard : Arc
{
public string Log = "";
public void Grow(ArcTests.Gates gates, int rings)
{
int mine = rings;
wait:
while (!gates.Open.Contains("ring" + rings))
{
Yield();
}
if (rings > 1)
{
deeper:
Grow(gates, rings - 1);
}
Log += mine + ";";
}
protected override void Run(ArcTests.Gates gates)
{
}
}
///
/// Runs the passage of another arc that calls itself.
///
public partial class Orchardist : Arc
{
public Orchard Trees = new Orchard();
protected override void Run(ArcTests.Gates gates)
{
plant:
Trees.Grow(gates, 2);
}
}
///
/// Holds a passage that calls itself in a base class, for the scripts that derive from it to run.
///
public abstract partial class Digging : Arc
{
public string Log = "";
protected void Dig(ArcTests.Gates gates, int depth)
{
int here = depth;
wait:
while (!gates.Open.Contains("dig" + depth))
{
Yield();
}
if (depth < 2)
{
deeper:
Dig(gates, depth + 1);
}
Log += here + ";";
}
}
public partial class Shaft : Digging
{
protected override void Run(ArcTests.Gates gates)
{
start:
Dig(gates, 1);
}
}
///
/// Calls its own passage down to the third level before it pauses there, and does nothing else while it waits.
///
public partial class Plunging : Arc
{
public int Spins;
private void Plunge(ArcTests.Gates gates, int level)
{
int mine = level;
if (level < 3)
{
deeper:
Plunge(gates, level + 1);
}
wait:
while (!gates.Open.Contains("go"))
{
++Spins;
Yield();
}
Spins += mine;
}
protected override void Run(ArcTests.Gates gates)
{
start:
Plunge(gates, 1);
}
}
///
/// Has a generic passage that calls itself with its type argument wrapped in a list, so every level is a frame of a
/// new type.
///
public partial class Widening : Arc
{
public string Log = "";
private static int Wrapping(System.Type type)
{
int depth = 0;
while (type.IsGenericType)
{
++depth;
type = type.GetGenericArguments()[0];
}
return depth;
}
private void Wrap(ArcTests.Gates gates, X item, int left)
{
X kept = item;
wait:
while (!gates.Open.Contains("wrap" + left))
{
Yield();
}
Log += Wrapping(typeof(X)) + "@" + left + ";";
if (left > 0)
{
deeper:
Wrap(gates, new System.Collections.Generic.List { kept }, left - 1);
}
Log += "up" + Wrapping(kept.GetType()) + ";";
}
protected override void Run(ArcTests.Gates gates)
{
start:
Wrap(gates, 7, 2);
}
}
///
/// Runs Run again from a passage that Run calls, so each lap has a frame for Run's locals.
///
public partial class Relapsing : Arc
{
public int Laps;
public string Log = "";
private void Again(ArcTests.Gates gates, int kept)
{
wait:
while (!gates.Open.Contains("lap" + kept))
{
Yield();
}
Log += "lap" + kept + ";";
if (kept < 2)
{
back:
Run(gates);
}
}
protected override void Run(ArcTests.Gates gates)
{
int lap = Laps++;
start:
Again(gates, lap);
Log += "end" + lap + ";";
}
}
///
/// Runs Run again from Run itself.
///
public partial class Repeating : Arc
{
public int Laps;
public string Log = "";
protected override void Run(ArcTests.Gates gates)
{
int lap = Laps++;
wait:
while (!gates.Open.Contains("round" + lap))
{
Yield();
}
Log += "round" + lap + ";";
if (lap < 2)
{
again:
Run(gates);
}
Log += "done" + lap + ";";
}
}
///
/// Has a Run that is part of a cycle, for a class that derives from it to override with a cycle of its own.
///
public partial class Cycling : Arc
{
public string Log = "";
public int Laps;
private void Pass(ArcTests.Gates gates, int kept)
{
wait:
while (!gates.Open.Contains("pass" + kept))
{
Yield();
}
Log += "pass" + kept + ";";
if (kept < 1)
{
back:
Run(gates);
}
}
protected override void Run(ArcTests.Gates gates)
{
int lap = Laps++;
start:
Pass(gates, lap);
}
}
public partial class CyclingChild : Cycling
{
private void Push(ArcTests.Gates gates, int kept)
{
wait:
while (!gates.Open.Contains("push" + kept))
{
Yield();
}
Log += "push" + kept + ";";
if (kept < 1)
{
back:
Run(gates);
}
}
protected override void Run(ArcTests.Gates gates)
{
int lap = Laps++;
start:
Push(gates, lap);
}
}
///
/// Calls its own generic passage without end, wrapping its type argument at every level.
///
public partial class Fathomless : Arc
{
public int Reached;
private void Sink(ArcTests.Gates gates, X item, int level)
{
Reached = level;
if (level < 0)
{
never:
while (!gates.Open.Contains("never"))
{
Yield();
}
}
deeper:
Sink(gates, new System.Collections.Generic.List { item }, level + 1);
}
protected override void Run(ArcTests.Gates gates)
{
start:
Sink(gates, 0, 0);
}
}
///
/// Calls its own passage without end, so only the stack stops it.
///
public partial class Bottomless : Arc
{
public int Reached;
private void Deeper(ArcTests.Gates gates, int level)
{
Reached = level;
if (level < 0)
{
never:
while (!gates.Open.Contains("never"))
{
Yield();
}
}
deeper:
Deeper(gates, level + 1);
}
protected override void Run(ArcTests.Gates gates)
{
start:
Deeper(gates, 0);
}
}
}