using System; using System.Collections.Generic; using System.Linq; namespace Ariadne.Vellum { /// /// Remembers the key and type of each field and local an arc class listed, in the order it listed them, and the /// same for each call it listed the locals of. /// public class ArcPartList : IArcPartLister { public readonly List Keys = new List(); public readonly List Types = new List(); public readonly List IsLocal = new List(); /// /// Holds the name of each call the arc class listed locals for. /// public readonly List ScopeNames = new List(); /// /// Holds what each of listed, in the same order. A call that repeats one above it /// holds that one's list, so the lists can form a cycle. /// public readonly List Scopes = new List(); /// /// Holds the name of each call that runs a frame whose type arguments only a save says. /// public readonly List PolymorphicNames = new List(); /// /// Holds the open generic frame class of each of , in the same order. /// public readonly List PolymorphicDefinitions = new List(); private readonly ArcPartList parent; private readonly Type[] frames; public ArcPartList() { } private ArcPartList(ArcPartList parent, Type[] frames) { this.parent = parent; this.frames = frames; } public int Count { get { return Keys.Count; } } public void Field(string key) { Keys.Add(key); Types.Add(typeof(T)); IsLocal.Add(false); } public void Local(string key) { Keys.Add(key); Types.Add(typeof(T)); IsLocal.Add(true); } public void Polymorphic(string name, Type frameDefinition) { PolymorphicNames.Add(name); PolymorphicDefinitions.Add(frameDefinition); } /// /// Returns the list for the call , which is the same one each time it's named, or null /// if a call above this one runs already. /// public IArcPartLister Scope(string name, params Type[] frames) { int index = ScopeNames.IndexOf(name); if (index >= 0) { // A repeat of a call above has nothing more to list. return Scopes[index].parent == this ? Scopes[index] : null; } for (ArcPartList above = this; above != null && frames.Length > 0; above = above.parent) { if (above.frames != null && above.frames.SequenceEqual(frames)) { ScopeNames.Add(name); Scopes.Add(above); return null; } } var returnMe = new ArcPartList(this, frames); ScopeNames.Add(name); Scopes.Add(returnMe); return returnMe; } } }