/src/Boo.Lang.Compiler/Ast/NodeCollection.cs
C# | 445 lines | 348 code | 66 blank | 31 comment | 53 complexity | af7a4f3338fd00e2ad47f78bbb22d851 MD5 | raw file
Possible License(s): GPL-2.0
- #region license
- // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without modification,
- // are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- // * Neither the name of Rodrigo B. de Oliveira nor the names of its
- // contributors may be used to endorse or promote products derived from this
- // software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
- // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- #endregion
-
- using System;
- using System.Collections;
- using System.Collections.Generic;
-
- namespace Boo.Lang.Compiler.Ast
- {
-
- /// <summary>
- /// Node collection base class.
- /// </summary>
- public class NodeCollection<T> : ICollection<T>, ICollection, ICloneable, IEquatable<NodeCollection<T>>
- where T : Node
- {
- private Node _parent;
- private readonly List<T> _list;
-
- protected NodeCollection()
- {
- _list = new List<T>();
- }
-
- protected NodeCollection(Node parent)
- {
- _parent = parent;
- _list = new List<T>();
- }
-
- protected NodeCollection(Node parent, IEnumerable<T> list)
- {
- if (null == list) throw new ArgumentNullException("list");
-
- _parent = parent;
- _list = new List<T>(list);
- }
-
- public T this[int index]
- {
- get { return _list[index]; }
- set
- {
- if (_list[index] == value)
- return;
- _list[index] = value;
- OnChanged();
- }
- }
-
- public IEnumerator<T> GetEnumerator()
- {
- return _list.GetEnumerator();
- }
-
- public Node ParentNode
- {
- get { return _parent; }
- }
-
- public bool IsEmpty
- {
- get { return 0 == _list.Count; }
- }
-
- public int Count
- {
- get { return _list.Count; }
- }
-
- public int IndexOf(T item)
- {
- return _list.IndexOf(item);
- }
-
- public bool IsReadOnly
- {
- get { return false; }
- }
-
- public bool IsSynchronized
- {
- get { return false; }
- }
-
- public object SyncRoot
- {
- get { return this; }
- }
-
- public void CopyTo(Array array, int index)
- {
- ((ICollection)_list).CopyTo(array, index);
- }
-
- public void CopyTo(T[] array, int index)
- {
- _list.CopyTo(array, index);
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return _list.GetEnumerator();
- }
-
- public void Clear()
- {
- _list.Clear();
- OnChanged();
- }
-
- public T[] ToArray()
- {
- return _list.ToArray();
- }
-
- public TOut[] ToArray<TOut>(Function<T, TOut> selector)
- {
- return _list.ToArray(selector);
- }
-
- public T[] ToReverseArray()
- {
- T[] array = ToArray();
- Array.Reverse(array);
- return array;
- }
-
- public IEnumerable<T> Except<UnwantedNodeType>() where UnwantedNodeType : T
- {
- foreach (T node in _list)
- if (!(node is UnwantedNodeType))
- yield return node;
- }
-
- public IEnumerable<T> Except<UnwantedNodeType,UnwantedNodeType2>()
- where UnwantedNodeType : T
- where UnwantedNodeType2 : T
- {
- foreach (T node in _list)
- if (!(node is UnwantedNodeType) && !(node is UnwantedNodeType2))
- yield return node;
- }
-
- protected IEnumerable InternalPopRange(int begin)
- {
- OnChanged();
- return _list.PopRange(begin);
- }
-
- public bool Contains(T node)
- {
- foreach (T n in _list)
- if (n == node) return true;
- return false;
- }
-
- [Obsolete("Use Contains(T node) instead.")]
- public bool ContainsNode(T node)
- {
- return Contains(node);
- }
-
- public bool Contains(Predicate<T> condition)
- {
- return _list.Contains(condition);
- }
-
- public bool ContainsEntity(TypeSystem.IEntity entity)
- {
- foreach (T node in _list)
- if (entity == node.Entity)
- return true;
- return false;
- }
-
- public Node RemoveByEntity(TypeSystem.IEntity entity)
- {
- if (null == entity)
- throw new ArgumentNullException("entity");
- for (int i = 0; i < _list.Count; ++i)
- {
- Node node = _list[i];
- if (entity == node.Entity)
- {
- RemoveAt(i);
- return node;
- }
- }
- return null;
- }
-
- public virtual object Clone()
- {
- var clone = (NodeCollection<T>)Activator.CreateInstance(GetType());
- var cloneList = clone._list;
- foreach (T node in _list)
- cloneList.Add((T)node.CloneNode());
- return clone;
- }
-
- public void ClearTypeSystemBindings()
- {
- foreach (T node in _list)
- node.ClearTypeSystemBindings();
- }
-
- internal List<T> InnerList
- {
- get { return _list; }
- }
-
- internal void InitializeParent(Node parent)
- {
- _parent = parent;
- foreach (T node in _list)
- node.InitializeParent(_parent);
- }
-
- public void Reject(Predicate<T> condition)
- {
- if (null == condition)
- throw new ArgumentNullException("condition");
-
- var index = 0;
- foreach (T node in ToArray())
- if (condition(node))
- RemoveAt(index);
- else
- ++index;
- }
-
- public void RemoveAt(int index)
- {
- //Node existing = (Node)InnerList[index];
- //existing.InitializeParent(null);
- _list.RemoveAt(index);
- OnChanged();
- }
-
- public void ExtendWithClones(IEnumerable<T> items)
- {
- foreach (T item in items)
- Add((T)item.CloneNode());
- }
-
- public void ReplaceAt(int i, T newItem)
- {
- Initialize(newItem);
- _list[i] = newItem;
- OnChanged();
- }
-
- public void Add(T item)
- {
- Initialize(item);
- _list.Add(item);
- OnChanged();
- }
-
- [Obsolete("Use AddRange")]
- public void Extend(IEnumerable<T> items)
- {
- AddRange(items);
- }
-
- public void AddRange(IEnumerable<T> items)
- {
- AssertNotNull("items", items);
- foreach (T item in items)
- Add(item);
- }
-
- public bool Replace(T existing, T newItem)
- {
- AssertNotNull("existing", existing);
- for (int i = 0; i < _list.Count; ++i)
- {
- if (this[i] == existing)
- {
- if (null == newItem)
- RemoveAt(i);
- else
- ReplaceAt(i, newItem);
- return true;
- }
- }
- return false;
- }
-
- public void Insert(int index, T item)
- {
- Initialize(item);
- _list.Insert(index, item);
- OnChanged();
- }
-
- public bool Remove(T item)
- {
- if (((ICollection<T>)_list).Remove(item))
- {
- OnChanged();
- return true;
- }
- return false;
- }
-
- public event EventHandler Changed;
-
- private void OnChanged()
- {
- var changed = Changed;
- if (changed != null)
- changed(this, EventArgs.Empty);
- }
-
- override public int GetHashCode()
- {
- return _list.GetHashCode();
- }
-
- override public bool Equals(object other)
- {
- return Equals(other as NodeCollection<T>);
- }
-
- public bool Equals(NodeCollection<T> other)
- {
- if (null == other) return false;
- if (this == other) return true;
- if (InnerList.Count != other.Count) return false;
-
- IEnumerator<T> enumerator = other.GetEnumerator();
- foreach (T mine in this)
- {
- if (!enumerator.MoveNext()) return false;
- if (!mine.Equals(enumerator.Current)) return false;
- }
- return true;
- }
-
- void Initialize(Node item)
- {
- AssertNotNull("item", item);
- if (null != _parent)
- item.InitializeParent(_parent);
- }
-
- private static void AssertNotNull(string descrip, object o)
- {
- if (o == null)
- throw new ArgumentException(String.Format("null reference for: {0}", descrip));
- }
-
- public NodeCollection<TNew> Cast<TNew>() where TNew : Node
- {
- return Cast<TNew>(0);
- }
-
- public NodeCollection<TNew> Cast<TNew>(int index) where TNew : Node
- {
- if (index < 0 || index > Count)
- throw new ArgumentOutOfRangeException("index");
-
- if (0 == (Count - index)) //empty or no item to cast
- return Empty<TNew>(ParentNode);
-
- NodeCollection<TNew> nodes = new NodeCollection<TNew>(ParentNode);
- int i = -1;
-
- foreach (T node in _list)
- {
- ++i;
- if (i < index)
- continue;
-
- TNew cnode = node as TNew;
- if (null == cnode)
- {
- ExpressionStatement es = node as ExpressionStatement;
- if (null != es)
- cnode = es.Expression as TNew;
- }
- if (null == cnode)
- throw new InvalidCastException(
- string.Format("Cannot cast item #{0} from `{1}` to `{2}`",
- i+1, node.GetType(), typeof(TNew)));
-
- nodes.Add(cnode);
- }
- return nodes;
- }
-
- public static NodeCollection<TNode> Empty<TNode>(Node parent) where TNode : Node
- {
- //TODO: cache?
- return new NodeCollection<TNode>(parent);
- }
-
- public bool StartsWith<TNode>() where TNode : T
- {
- return !IsEmpty && (First is TNode);
- }
-
- public bool EndsWith<TNode>() where TNode : T
- {
- return !IsEmpty && (Last is TNode);
- }
-
- public T First
- {
- get { return (IsEmpty ? null : _list[0]); }
- }
-
- public T Last
- {
- get { return (IsEmpty ? null : _list[Count - 1]); }
- }
- }
- }