Skip to content

Instantly share code, notes, and snippets.

@aalmada
Last active April 15, 2024 10:47
Show Gist options
  • Save aalmada/a1edba42d27df7524b9f13c5e9fdfd34 to your computer and use it in GitHub Desktop.
Save aalmada/a1edba42d27df7524b9f13c5e9fdfd34 to your computer and use it in GitHub Desktop.
/*
SharpLab tools in Run mode:
• value.Inspect()
• Inspect.Heap(object)
• Inspect.Stack(value)
• Inspect.MemoryGraph(value1, value2, …)
*/
using System;
using System.Collections.Generic;
var root = ParallelAll([
Invert(Repeat(WriteLineRange(0, 4), 2)),
WriteLineRange(10, 10),
]);
foreach(var _ in root)
{
Console.WriteLine("-");
}
static IEnumerable<BehaviorStatus> Succeed()
{
yield return BehaviorStatus.Succeeded;
}
static IEnumerable<BehaviorStatus> Fail()
{
yield return BehaviorStatus.Failed;
}
static IEnumerable<BehaviorStatus> Sequence(IEnumerable<BehaviorStatus>[] children)
{
ArgumentNullException.ThrowIfNull(children);
return GetEnumerable(children);
static IEnumerable<BehaviorStatus> GetEnumerable(IEnumerable<BehaviorStatus>[] children)
{
for(var index = 0; index < children.Length; index++)
{
var child = children[index];
foreach(var status in child)
{
switch(status)
{
case BehaviorStatus.Running:
yield return BehaviorStatus.Running;
break;
case BehaviorStatus.Succeeded:
goto childSucceeded;
case BehaviorStatus.Failed:
yield return BehaviorStatus.Failed;
yield break;
}
}
childSucceeded:
if(index < children.Length - 1)
yield return BehaviorStatus.Running;
}
yield return BehaviorStatus.Succeeded;
}
}
static IEnumerable<BehaviorStatus> Select(IEnumerable<BehaviorStatus>[] children)
{
ArgumentNullException.ThrowIfNull(children);
return GetEnumerable(children);
static IEnumerable<BehaviorStatus> GetEnumerable(IEnumerable<BehaviorStatus>[] children)
{
for(var index = 0; index < children.Length; index++)
{
var child = children[index];
foreach(var status in child)
{
switch(status)
{
case BehaviorStatus.Running:
yield return BehaviorStatus.Running;
break;
case BehaviorStatus.Succeeded:
yield return BehaviorStatus.Succeeded;
yield break;
case BehaviorStatus.Failed:
goto childFailed;
}
}
childFailed:
if(index < children.Length - 1)
yield return BehaviorStatus.Running;
}
yield return BehaviorStatus.Failed;
}
}
static IEnumerable<BehaviorStatus> ParallelAny(IEnumerable<BehaviorStatus>[] children)
{
ArgumentNullException.ThrowIfNull(children);
return GetEnumerable(children);
static IEnumerable<BehaviorStatus> GetEnumerable(IEnumerable<BehaviorStatus>[] children)
{
var enumerators = new IEnumerator<BehaviorStatus>[children.Length];
for (var index = 0; index < enumerators.Length && index < children.Length; index++)
enumerators[index] = children[index].GetEnumerator();
try
{
while(true)
{
foreach(var enumerator in enumerators)
{
enumerator.MoveNext();
switch(enumerator.Current)
{
case BehaviorStatus.Succeeded:
yield return BehaviorStatus.Succeeded;
yield break;
case BehaviorStatus.Failed:
yield return BehaviorStatus.Failed;
yield break;
}
}
yield return BehaviorStatus.Running;
}
}
finally
{
foreach(var enumerator in enumerators)
enumerator.Dispose();
}
}
}
static IEnumerable<BehaviorStatus> ParallelAll(IEnumerable<BehaviorStatus>[] children)
{
ArgumentNullException.ThrowIfNull(children);
return GetEnumerable(children);
static IEnumerable<BehaviorStatus> GetEnumerable(IEnumerable<BehaviorStatus>[] children)
{
var enumerators = new BehaviorEnumerator[children.Length];
for (var index = 0; index < enumerators.Length && index < children.Length; index++)
enumerators[index] = new BehaviorEnumerator { Instance = children[index].GetEnumerator() };
try
{
var succeededCounter = 0;
while(true)
{
foreach(var enumerator in enumerators)
{
if(!enumerator.Succeeded)
{
enumerator.Instance.MoveNext();
switch(enumerator.Instance.Current)
{
case BehaviorStatus.Succeeded:
enumerator.Succeeded = true;
succeededCounter++;
if(succeededCounter == children.Length)
{
yield return BehaviorStatus.Succeeded;
yield break;
}
break;
case BehaviorStatus.Failed:
yield return BehaviorStatus.Failed;
yield break;
}
}
}
yield return BehaviorStatus.Running;
}
}
finally
{
foreach(var enumerator in enumerators)
enumerator.Instance.Dispose();
}
}
}
static IEnumerable<BehaviorStatus> Invert(IEnumerable<BehaviorStatus> child)
{
ArgumentNullException.ThrowIfNull(child);
return GetEnumerable(child);
static IEnumerable<BehaviorStatus> GetEnumerable(IEnumerable<BehaviorStatus> child)
{
foreach(var status in child)
{
switch(status)
{
case BehaviorStatus.Running:
yield return BehaviorStatus.Running;
break;
case BehaviorStatus.Succeeded:
yield return BehaviorStatus.Failed;
yield break;
case BehaviorStatus.Failed:
yield return BehaviorStatus.Succeeded;
yield break;
}
}
}
}
static IEnumerable<BehaviorStatus> Repeat(IEnumerable<BehaviorStatus> child, int count)
{
ArgumentNullException.ThrowIfNull(child);
ArgumentOutOfRangeException.ThrowIfNegative(count);
return GetEnumerable(child, count);
static IEnumerable<BehaviorStatus> GetEnumerable(IEnumerable<BehaviorStatus> child, int count)
{
for(var counter = 0; counter < count; counter++)
{
foreach(var status in child)
{
switch(status)
{
case BehaviorStatus.Running:
yield return BehaviorStatus.Running;
break;
case BehaviorStatus.Succeeded:
goto childSucceeded;
case BehaviorStatus.Failed:
yield return BehaviorStatus.Failed;
yield break;
}
}
childSucceeded:
if(counter < count - 1)
yield return BehaviorStatus.Running;
}
yield return BehaviorStatus.Succeeded;
}
}
static IEnumerable<BehaviorStatus> RepeatUntilFail(IEnumerable<BehaviorStatus> child)
{
ArgumentNullException.ThrowIfNull(child);
return GetEnumerable(child);
static IEnumerable<BehaviorStatus> GetEnumerable(IEnumerable<BehaviorStatus> child)
{
while(true)
{
foreach(var status in child)
{
switch(status)
{
case BehaviorStatus.Running:
yield return BehaviorStatus.Running;
break;
case BehaviorStatus.Succeeded:
goto childSucceeded;
case BehaviorStatus.Failed:
yield return BehaviorStatus.Succeeded;
yield break;
}
}
childSucceeded:
yield return BehaviorStatus.Running;
}
}
}
static IEnumerable<BehaviorStatus> WriteLine(string? message)
{
Console.WriteLine(message);
yield return BehaviorStatus.Succeeded;
}
static IEnumerable<BehaviorStatus> WriteLineRange(int start, int count)
{
ArgumentOutOfRangeException.ThrowIfNegative(count);
return GetEnumerable(start, count);
static IEnumerable<BehaviorStatus> GetEnumerable(int start, int count)
{
var end = start + count;
for(var value = start; value < end; value++)
{
Console.WriteLine(value);
if(value < end - 1)
yield return BehaviorStatus.Running;
}
yield return BehaviorStatus.Succeeded;
}
}
enum BehaviorStatus { Running, Succeeded, Failed };
class BehaviorEnumerator
{
public required IEnumerator<BehaviorStatus> Instance { get; init; }
public bool Succeeded { get; set; } = false;
}
0
10
-
1
11
-
2
12
-
3
13
-
0
14
-
1
15
-
2
16
-
3
-
{
"version": 1,
"target": "Run",
"mode": "Release",
"branch": "core-x64"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment