using System; using System.Collections.Generic; public class Amb : IDisposable { List streams = new List(); List assertsOrActions = new List(); volatile bool stopped = false; public IAmbValue DefineValues(params T[] values) { return DefineValueSet(values); } public IAmbValue DefineValueSet(IEnumerable values) { ValueSet stream = new ValueSet(); stream.Enumerable = values; streams.Add(stream); return stream; } public Amb Assert(Func function) { assertsOrActions.Add(new AmbAssert() { Level = streams.Count, IsValidFunction = function }); return this; } public Amb Perform(Action action) { assertsOrActions.Add(new AmbAction() { Level = streams.Count, Action = action }); return this; } public void Stop() { stopped = true; } public void Dispose() { RunLevel(0, 0); if (!stopped) { throw new AmbException(); } } void RunLevel(int level, int actionIndex) { while (actionIndex < assertsOrActions.Count && assertsOrActions[actionIndex].Level <= level) { if (!assertsOrActions[actionIndex].Invoke() || stopped) return; actionIndex++; } if (level < streams.Count) { using (IValueSetIterator iterator = streams[level].CreateIterator()) { while (iterator.MoveNext()) { RunLevel(level + 1, actionIndex); } } } } interface IValueSet { IValueSetIterator CreateIterator(); } interface IValueSetIterator : IDisposable { bool MoveNext(); } interface IAssertOrAction { int Level { get; } bool Invoke(); } class AmbAssert : IAssertOrAction { internal int Level; internal Func IsValidFunction; int IAssertOrAction.Level { get { return Level; } } bool IAssertOrAction.Invoke() { return IsValidFunction(); } } class AmbAction : IAssertOrAction { internal int Level; internal Action Action; int IAssertOrAction.Level { get { return Level; } } bool IAssertOrAction.Invoke() { Action(); return true; } } class ValueSet : IValueSet, IAmbValue, IValueSetIterator { internal IEnumerable Enumerable; private IEnumerator enumerator; public T Value { get { return enumerator.Current; } } public IValueSetIterator CreateIterator() { enumerator = Enumerable.GetEnumerator(); return this; } public bool MoveNext() { return enumerator.MoveNext(); } public void Dispose() { enumerator.Dispose(); } } } public interface IAmbValue { T Value { get; } } public class AmbException : Exception { public AmbException() : base("AMB is angry") { } }