PageRenderTime 142ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/Dependencies/boo/src/Boo.Lang.Compiler/Ast/Node.cs

https://github.com/w4x/boolangstudio
C# | 368 lines | 267 code | 53 blank | 48 comment | 42 complexity | 2b343f1475719f1e4fd0e2acd2acf573 MD5 | raw file
Possible License(s): GPL-2.0
  1. #region license
  2. // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Rodrigo B. de Oliveira nor the names of its
  14. // contributors may be used to endorse or promote products derived from this
  15. // software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  21. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #endregion
  28. using System.Collections.Generic;
  29. namespace Boo.Lang.Compiler.Ast
  30. {
  31. using System;
  32. using System.Xml.Serialization;
  33. public delegate bool NodePredicate(Node node);
  34. /// <summary>
  35. /// Base class for every node in the AST.
  36. /// </summary>
  37. [Serializable]
  38. public abstract class Node : ICloneable
  39. {
  40. public static bool Matches<T>(T lhs, T rhs) where T : Node
  41. {
  42. return lhs == null ? rhs == null : lhs.Matches(rhs);
  43. }
  44. public static bool Matches(Block lhs, Block rhs)
  45. {
  46. return lhs == null ? rhs == null || !rhs.HasStatements : lhs.Matches(rhs);
  47. }
  48. public static bool AllMatch<T>(IEnumerable<T> lhs, IEnumerable<T> rhs) where T : Node
  49. {
  50. if (lhs == null) return rhs == null || IsEmpty(rhs);
  51. if (rhs == null) return IsEmpty(lhs);
  52. IEnumerator<T> r = rhs.GetEnumerator();
  53. foreach (T item in lhs)
  54. {
  55. if (!r.MoveNext()) return false;
  56. if (!Matches(item, r.Current)) return false;
  57. }
  58. if (r.MoveNext()) return false;
  59. return true;
  60. }
  61. private static bool IsEmpty<T>(IEnumerable<T> e)
  62. {
  63. return !e.GetEnumerator().MoveNext();
  64. }
  65. protected LexicalInfo _lexicalInfo = LexicalInfo.Empty;
  66. protected SourceLocation _endSourceLocation = LexicalInfo.Empty;
  67. protected Node _parent;
  68. protected string _documentation;
  69. protected System.Collections.Hashtable _annotations;
  70. protected bool _isSynthetic;
  71. protected Node()
  72. {
  73. _lexicalInfo = LexicalInfo.Empty;
  74. }
  75. protected Node(LexicalInfo lexicalInfo)
  76. {
  77. if (null == lexicalInfo)
  78. {
  79. throw new ArgumentNullException("lexicalInfo");
  80. }
  81. _lexicalInfo = lexicalInfo;
  82. }
  83. protected void InitializeFrom(Node other)
  84. {
  85. _lexicalInfo = other.LexicalInfo;
  86. _isSynthetic = other.IsSynthetic;
  87. }
  88. public Node CloneNode()
  89. {
  90. return (Node)Clone();
  91. }
  92. /// <summary>
  93. /// true when the node was constructed by the compiler.
  94. /// </summary>
  95. [XmlAttribute]
  96. [System.ComponentModel.DefaultValue(false)]
  97. public bool IsSynthetic
  98. {
  99. get
  100. {
  101. return _isSynthetic;
  102. }
  103. set
  104. {
  105. _isSynthetic = value;
  106. }
  107. }
  108. [XmlIgnore]
  109. internal Boo.Lang.Compiler.TypeSystem.IEntity Entity
  110. {
  111. get
  112. {
  113. return Boo.Lang.Compiler.TypeSystem.TypeSystemServices.GetOptionalEntity(this);
  114. }
  115. set
  116. {
  117. Boo.Lang.Compiler.TypeSystem.TypeSystemServices.Bind(this, value);
  118. }
  119. }
  120. public object this[object key]
  121. {
  122. get
  123. {
  124. if (_annotations == null) return null;
  125. return _annotations[key];
  126. }
  127. set
  128. {
  129. if (_annotations == null) _annotations = new System.Collections.Hashtable();
  130. _annotations[key] = value;
  131. }
  132. }
  133. public void Annotate(object key)
  134. {
  135. Annotate(key, key);
  136. }
  137. public void Annotate(object key, object value)
  138. {
  139. if (_annotations == null) _annotations = new System.Collections.Hashtable();
  140. _annotations.Add(key, value);
  141. }
  142. public bool ContainsAnnotation(object key)
  143. {
  144. if (_annotations == null) return false;
  145. return _annotations.ContainsKey(key);
  146. }
  147. public void RemoveAnnotation(object key)
  148. {
  149. if (_annotations == null) return;
  150. _annotations.Remove(key);
  151. }
  152. internal virtual void ClearTypeSystemBindings()
  153. {
  154. _annotations = null;
  155. }
  156. public Node ParentNode
  157. {
  158. get
  159. {
  160. return _parent;
  161. }
  162. }
  163. public string Documentation
  164. {
  165. get
  166. {
  167. return _documentation;
  168. }
  169. set
  170. {
  171. _documentation = value;
  172. }
  173. }
  174. [XmlIgnore]
  175. public LexicalInfo LexicalInfo
  176. {
  177. get
  178. {
  179. if(_lexicalInfo.Equals(LexicalInfo.Empty) && null != ParentNode && null != ParentNode.LexicalInfo)
  180. {
  181. _lexicalInfo = ParentNode.LexicalInfo;
  182. }
  183. return _lexicalInfo;
  184. }
  185. set
  186. {
  187. if (null == value)
  188. {
  189. throw new ArgumentNullException("LexicalInfo");
  190. }
  191. _lexicalInfo = value;
  192. }
  193. }
  194. /// <summary>
  195. /// Where this element ends in the source file.
  196. /// This information is generally available and/or accurate
  197. /// only for blocks and type definitions.
  198. /// </summary>
  199. [System.Xml.Serialization.XmlIgnore]
  200. public virtual SourceLocation EndSourceLocation
  201. {
  202. get
  203. {
  204. return _endSourceLocation;
  205. }
  206. set
  207. {
  208. if (null == value)
  209. {
  210. throw new ArgumentNullException("EndSourceLocation");
  211. }
  212. _endSourceLocation = value;
  213. }
  214. }
  215. public virtual bool Replace(Node existing, Node newNode)
  216. {
  217. if (null == existing)
  218. {
  219. throw new ArgumentNullException("existing");
  220. }
  221. return false;
  222. }
  223. private class ReplaceVisitor : DepthFirstTransformer
  224. {
  225. NodePredicate _predicate;
  226. Node _template;
  227. int _matches;
  228. public ReplaceVisitor(NodePredicate predicate, Node template)
  229. {
  230. _predicate = predicate;
  231. _template = template;
  232. }
  233. public int Matches
  234. {
  235. get
  236. {
  237. return _matches;
  238. }
  239. }
  240. override protected void OnNode(Node node)
  241. {
  242. if (_predicate(node))
  243. {
  244. ++_matches;
  245. ReplaceCurrentNode(_template.CloneNode());
  246. }
  247. else
  248. {
  249. base.OnNode(node);
  250. }
  251. }
  252. }
  253. /// <summary>
  254. /// Replaces all occurrences of the pattern pattern anywhere in the tree
  255. /// with a clone of template.
  256. /// </summary>
  257. /// <returns>the number of nodes replaced</returns>
  258. public int ReplaceNodes(Node pattern, Node template)
  259. {
  260. NodePredicate predicate = new NodePredicate(pattern.Matches);
  261. return ReplaceNodes(predicate, template);
  262. }
  263. /// <summary>
  264. /// Replaces all node for which predicate returns true anywhere in the tree
  265. /// with a clone of template.
  266. /// </summary>
  267. /// <returns>the number of nodes replaced</returns>
  268. public int ReplaceNodes(NodePredicate predicate, Node template)
  269. {
  270. ReplaceVisitor visitor = new ReplaceVisitor(predicate, template);
  271. Accept(visitor);
  272. return visitor.Matches;
  273. }
  274. internal void InitializeParent(Node parent)
  275. {
  276. _parent = parent;
  277. }
  278. public abstract void Accept(IAstVisitor visitor);
  279. public abstract object Clone();
  280. public abstract bool Matches(Node other);
  281. protected bool NoMatch(string fieldName)
  282. {
  283. //helps debugging Node.Matches logic
  284. //Console.Error.WriteLine("No match for '{0}'.", fieldName);
  285. return false;
  286. }
  287. public abstract NodeType NodeType
  288. {
  289. get;
  290. }
  291. override public string ToString()
  292. {
  293. return ToCodeString();
  294. }
  295. public string ToCodeString()
  296. {
  297. System.IO.StringWriter writer = new System.IO.StringWriter();
  298. new Visitors.BooPrinterVisitor(writer).Visit(this);
  299. return writer.ToString();
  300. }
  301. public Node GetAncestor(NodeType ancestorType)
  302. {
  303. Node parent = this.ParentNode;
  304. while (null != parent)
  305. {
  306. if (ancestorType == parent.NodeType)
  307. {
  308. return parent;
  309. }
  310. parent = parent.ParentNode;
  311. }
  312. return null;
  313. }
  314. }
  315. }