PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Boo.Lang.Compiler/CompilerPipeline.cs

https://github.com/boo/boo-lang
C# | 325 lines | 249 code | 47 blank | 29 comment | 35 complexity | 463d86650c20587130f9d7a258ed086d 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. namespace Boo.Lang.Compiler
  29. {
  30. using System;
  31. using System.Reflection;
  32. public class CompilerPipelineEventArgs : EventArgs
  33. {
  34. public readonly CompilerContext Context;
  35. public CompilerPipelineEventArgs(CompilerContext context)
  36. {
  37. this.Context = context;
  38. }
  39. }
  40. public class CompilerStepEventArgs : CompilerPipelineEventArgs
  41. {
  42. public readonly ICompilerStep Step;
  43. public CompilerStepEventArgs(CompilerContext context, ICompilerStep step) : base(context)
  44. {
  45. this.Step = step;
  46. }
  47. }
  48. public delegate void CompilerStepEventHandler(object sender, CompilerStepEventArgs args);
  49. /// <summary>
  50. /// A ordered set of <see cref="ICompilerStep"/> implementations
  51. /// that should be executed in sequence.
  52. /// </summary>
  53. public class CompilerPipeline
  54. {
  55. public event EventHandler<CompilerPipelineEventArgs> Before;
  56. public event EventHandler<CompilerPipelineEventArgs> After;
  57. public event CompilerStepEventHandler BeforeStep;
  58. public event CompilerStepEventHandler AfterStep;
  59. public static CompilerPipeline GetPipeline(string name)
  60. {
  61. if (null == name) throw new ArgumentNullException("name");
  62. switch (name)
  63. {
  64. case "parse": return new Pipelines.Parse();
  65. case "compile": return new Pipelines.Compile();
  66. case "run": return new Pipelines.Run();
  67. case "default": return new Pipelines.CompileToFile();
  68. case "verify": return new Pipelines.CompileToFileAndVerify();
  69. case "roundtrip": return new Pipelines.ParseAndPrint();
  70. case "boo": return new Pipelines.CompileToBoo();
  71. case "ast": return new Pipelines.ParseAndPrintAst();
  72. case "xml": return new Pipelines.ParseAndPrintXml();
  73. case "checkforerrors": return new Pipelines.CheckForErrors();
  74. case "dumpreferences":
  75. {
  76. CompilerPipeline pipeline = new Pipelines.CompileToBoo();
  77. pipeline.Add(new Boo.Lang.Compiler.Steps.DumpReferences());
  78. return pipeline;
  79. }
  80. }
  81. return LoadCustomPipeline(name);
  82. }
  83. private static CompilerPipeline LoadCustomPipeline(string typeName)
  84. {
  85. if (typeName.IndexOf(',') < 0)
  86. throw new ArgumentException(Boo.Lang.ResourceManager.Format("BooC.InvalidPipeline", typeName));
  87. return (CompilerPipeline)Activator.CreateInstance(FindPipelineType(typeName));
  88. }
  89. private static System.Type FindPipelineType(string typeName)
  90. {
  91. Assembly loaded = FindLoadedAssembly(AssemblySimpleNameFromFullTypeName(typeName));
  92. if (null != loaded) return loaded.GetType(SimpleTypeNameFromFullTypeName(typeName));
  93. return Type.GetType(typeName, true);
  94. }
  95. private static string SimpleTypeNameFromFullTypeName(string name)
  96. {
  97. return name.Split(',')[0].Trim();
  98. }
  99. private static string AssemblySimpleNameFromFullTypeName(string name)
  100. {
  101. return name.Split(',')[1].Trim();
  102. }
  103. private static Assembly FindLoadedAssembly(string assemblyName)
  104. {
  105. foreach (Assembly loaded in AppDomain.CurrentDomain.GetAssemblies())
  106. {
  107. if (loaded.GetName().Name == assemblyName) return loaded;
  108. }
  109. return null;
  110. }
  111. protected Boo.Lang.List _items;
  112. protected bool _breakOnErrors;
  113. public CompilerPipeline()
  114. {
  115. _items = new Boo.Lang.List();
  116. _breakOnErrors = true;
  117. }
  118. public bool BreakOnErrors
  119. {
  120. get { return _breakOnErrors; }
  121. set { _breakOnErrors = value; }
  122. }
  123. public CompilerPipeline Add(ICompilerStep step)
  124. {
  125. if (null == step) throw new ArgumentNullException("step");
  126. _items.Add(step);
  127. return this;
  128. }
  129. public CompilerPipeline RemoveAt(int index)
  130. {
  131. _items.RemoveAt(index);
  132. return this;
  133. }
  134. public CompilerPipeline Insert(int index, ICompilerStep step)
  135. {
  136. if (null == step) throw new ArgumentNullException("step");
  137. _items.Insert(index, step);
  138. return this;
  139. }
  140. public CompilerPipeline InsertAfter(Type stepExactType, ICompilerStep step)
  141. {
  142. return Insert(Find(stepExactType)+1, step);
  143. }
  144. public CompilerPipeline InsertBefore(Type stepExactType, ICompilerStep step)
  145. {
  146. return Insert(Find(stepExactType)-1, step);
  147. }
  148. public CompilerPipeline Replace(Type stepExactType, ICompilerStep step)
  149. {
  150. if (null == step) throw new ArgumentNullException("step");
  151. int index = Find(stepExactType);
  152. if (-1 == index) throw new ArgumentException("stepExactType");
  153. _items[index] = step;
  154. return this;
  155. }
  156. public int Find(Type stepExactType)
  157. {
  158. if (null == stepExactType) throw new ArgumentNullException("stepExactType");
  159. for (int i=0; i<_items.Count; ++i)
  160. {
  161. if (_items[i].GetType() == stepExactType)
  162. {
  163. return i;
  164. }
  165. }
  166. return -1;
  167. }
  168. public ICompilerStep Get(Type stepExactType)
  169. {
  170. int index = Find(stepExactType);
  171. if (-1 == index) return null;
  172. return (ICompilerStep)_items[index];
  173. }
  174. public int Count
  175. {
  176. get { return _items.Count; }
  177. }
  178. public ICompilerStep this[int index]
  179. {
  180. get { return (ICompilerStep)_items[index]; }
  181. set
  182. {
  183. if (null == value) throw new ArgumentNullException("value");
  184. _items[index] = value;
  185. }
  186. }
  187. virtual public void Clear()
  188. {
  189. _items.Clear();
  190. }
  191. virtual protected void OnBefore(CompilerContext context)
  192. {
  193. if (null != Before)
  194. {
  195. Before(this, new CompilerPipelineEventArgs(context));
  196. }
  197. }
  198. virtual protected void OnAfter(CompilerContext context)
  199. {
  200. if (null != After)
  201. {
  202. After(this, new CompilerPipelineEventArgs(context));
  203. }
  204. }
  205. virtual protected void OnBeforeStep(CompilerContext context, ICompilerStep step)
  206. {
  207. if (null != BeforeStep)
  208. {
  209. BeforeStep(this, new CompilerStepEventArgs(context, step));
  210. }
  211. }
  212. virtual protected void OnAfterStep(CompilerContext context, ICompilerStep step)
  213. {
  214. if (null != AfterStep)
  215. {
  216. AfterStep(this, new CompilerStepEventArgs(context, step));
  217. }
  218. }
  219. virtual protected void Prepare(CompilerContext context)
  220. {
  221. }
  222. virtual public void Run(CompilerContext context)
  223. {
  224. context.Run(DoRun);
  225. }
  226. protected void DoRun(CompilerContext context)
  227. {
  228. OnBefore(context);
  229. try
  230. {
  231. Prepare(context);
  232. RunSteps(context);
  233. DisposeSteps();
  234. } finally {
  235. OnAfter(context);
  236. }
  237. }
  238. private void DisposeSteps()
  239. {
  240. foreach (ICompilerStep step in _items)
  241. {
  242. step.Dispose();
  243. }
  244. }
  245. private void RunSteps(CompilerContext context)
  246. {
  247. foreach (ICompilerStep step in _items)
  248. {
  249. RunStep(context, step);
  250. if (_breakOnErrors && context.Errors.Count > 0)
  251. {
  252. break;
  253. }
  254. }
  255. }
  256. protected void RunStep(CompilerContext context, ICompilerStep step)
  257. {
  258. OnBeforeStep(context, step);
  259. step.Initialize(context);
  260. try
  261. {
  262. step.Run();
  263. }
  264. catch (Boo.Lang.Compiler.CompilerError error)
  265. {
  266. context.Errors.Add(error);
  267. }
  268. catch (System.Exception x)
  269. {
  270. context.Errors.Add(CompilerErrorFactory.StepExecutionError(x, step));
  271. }
  272. finally
  273. {
  274. OnAfterStep(context, step);
  275. }
  276. }
  277. }
  278. }