/mcs/class/System.ServiceModel/Mono.CodeGeneration/CodeBuilder.cs

https://github.com/t-ashula/mono · C# · 425 lines · 326 code · 66 blank · 33 comment · 74 complexity · b44ef3f1d39ff1df632e54279b1fa939 MD5 · raw file

  1. //
  2. // Permission is hereby granted, free of charge, to any person obtaining
  3. // a copy of this software and associated documentation files (the
  4. // "Software"), to deal in the Software without restriction, including
  5. // without limitation the rights to use, copy, modify, merge, publish,
  6. // distribute, sublicense, and/or sell copies of the Software, and to
  7. // permit persons to whom the Software is furnished to do so, subject to
  8. // the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be
  11. // included in all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  17. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  18. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  19. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. //
  21. // Copyright (C) Lluis Sanchez Gual, 2004
  22. //
  23. #if !FULL_AOT_RUNTIME
  24. using System;
  25. using System.IO;
  26. using System.Collections;
  27. using System.Reflection.Emit;
  28. using System.Reflection;
  29. namespace Mono.CodeGeneration
  30. {
  31. public class CodeBuilder
  32. {
  33. CodeBlock mainBlock;
  34. CodeBlock currentBlock;
  35. Stack blockStack = new Stack ();
  36. int varId;
  37. Label returnLabel;
  38. ArrayList nestedIfs = new ArrayList();
  39. int currentIfSerie = -1;
  40. CodeClass codeClass;
  41. public CodeBuilder (CodeClass codeClass)
  42. {
  43. this.codeClass = codeClass;
  44. mainBlock = new CodeBlock ();
  45. currentBlock = mainBlock;
  46. }
  47. CodeBuilder (CodeBlock block)
  48. {
  49. currentBlock = block;
  50. }
  51. public CodeBlock CurrentBlock
  52. {
  53. get {
  54. return currentBlock;
  55. }
  56. }
  57. public CodeClass OwnerClass
  58. {
  59. get { return codeClass; }
  60. }
  61. public void Generate (ILGenerator gen)
  62. {
  63. // try {
  64. mainBlock.Generate (gen);
  65. /*
  66. }
  67. catch (Exception ex) {
  68. string m = ex.Message + "\nCode block:\n";
  69. m += "-----------------------\n";
  70. m += PrintCode ();
  71. m += "-----------------------\n";
  72. throw new Exception (m, ex);
  73. }
  74. */
  75. }
  76. public string PrintCode ()
  77. {
  78. StringWriter sw = new StringWriter ();
  79. CodeWriter cw = new CodeWriter (sw);
  80. PrintCode (cw);
  81. return sw.ToString ();
  82. }
  83. public void PrintCode (CodeWriter cp)
  84. {
  85. mainBlock.PrintCode (cp);
  86. }
  87. public CodeVariableReference DeclareVariable (Type type)
  88. {
  89. return DeclareVariable (type, null);
  90. }
  91. public CodeVariableReference DeclareVariable (Type type, object ob)
  92. {
  93. return DeclareVariable (type, Exp.Literal(ob));
  94. }
  95. public CodeVariableReference DeclareVariable (CodeExpression initValue)
  96. {
  97. return DeclareVariable (initValue.GetResultType(), initValue);
  98. }
  99. public CodeVariableReference DeclareVariable (Type type, CodeExpression initValue)
  100. {
  101. string name = "v" + (varId++);
  102. CodeVariableDeclaration var = new CodeVariableDeclaration (type, name);
  103. currentBlock.Add (var);
  104. if (!object.ReferenceEquals (initValue, null))
  105. Assign (var.Variable, initValue);
  106. return var.Variable;
  107. }
  108. public void Assign (CodeValueReference var, CodeExpression val)
  109. {
  110. currentBlock.Add (new CodeAssignment (var, val));
  111. }
  112. public void If (CodeExpression condition)
  113. {
  114. currentBlock.Add (new CodeIf (condition));
  115. PushNewBlock ();
  116. nestedIfs.Add (0);
  117. }
  118. public void ElseIf (CodeExpression condition)
  119. {
  120. if (nestedIfs.Count == 0)
  121. throw new InvalidOperationException ("'Else' not allowed here");
  122. Else ();
  123. currentBlock.Add (new CodeIf (condition));
  124. PushNewBlock ();
  125. nestedIfs [nestedIfs.Count-1] = 1 + (int)nestedIfs [nestedIfs.Count-1];
  126. }
  127. public void Else ()
  128. {
  129. CodeBlock block = PopBlock ();
  130. CodeIf cif = currentBlock.GetLastItem () as CodeIf;
  131. if (cif == null || cif.TrueBlock != null)
  132. throw new InvalidOperationException ("'Else' not allowed here");
  133. cif.TrueBlock = block;
  134. PushNewBlock ();
  135. }
  136. public void EndIf ()
  137. {
  138. CodeBlock block = PopBlock ();
  139. CodeIf cif = currentBlock.GetLastItem () as CodeIf;
  140. if (cif == null || cif.FalseBlock != null || nestedIfs.Count == 0)
  141. throw new InvalidOperationException ("'EndIf' not allowed here");
  142. if (cif.TrueBlock == null)
  143. cif.TrueBlock = block;
  144. else
  145. cif.FalseBlock = block;
  146. int num = (int) nestedIfs [nestedIfs.Count-1];
  147. if (num > 0) {
  148. nestedIfs [nestedIfs.Count-1] = --num;
  149. EndIf ();
  150. }
  151. else {
  152. nestedIfs.RemoveAt (nestedIfs.Count - 1);
  153. }
  154. }
  155. public void Select ()
  156. {
  157. currentBlock.Add (new CodeSelect ());
  158. PushNewBlock ();
  159. }
  160. public void Case (CodeExpression condition)
  161. {
  162. PopBlock ();
  163. CodeSelect select = currentBlock.GetLastItem () as CodeSelect;
  164. if (select == null)
  165. throw new InvalidOperationException ("'Case' not allowed here");
  166. PushNewBlock ();
  167. select.AddCase (condition, currentBlock);
  168. }
  169. public void EndSelect ()
  170. {
  171. PopBlock ();
  172. CodeSelect select = currentBlock.GetLastItem () as CodeSelect;
  173. if (select == null)
  174. throw new InvalidOperationException ("'EndSelect' not allowed here");
  175. }
  176. public void While (CodeExpression condition)
  177. {
  178. currentBlock.Add (new CodeWhile (condition));
  179. PushNewBlock ();
  180. }
  181. public void EndWhile ()
  182. {
  183. CodeBlock block = PopBlock ();
  184. CodeWhile cif = currentBlock.GetLastItem () as CodeWhile;
  185. if (cif == null || cif.WhileBlock != null)
  186. throw new InvalidOperationException ("'EndWhile' not allowed here");
  187. cif.WhileBlock = block;
  188. }
  189. public void Foreach (Type type, out CodeExpression item, CodeExpression array)
  190. {
  191. CodeForeach cfe = new CodeForeach (array, type);
  192. item = cfe.ItemExpression;
  193. currentBlock.Add (cfe);
  194. PushNewBlock ();
  195. }
  196. public void EndForeach ()
  197. {
  198. CodeBlock block = PopBlock ();
  199. CodeForeach cif = currentBlock.GetLastItem () as CodeForeach;
  200. if (cif == null || cif.ForBlock != null)
  201. throw new InvalidOperationException ("'EndForeach' not allowed here");
  202. cif.ForBlock = block;
  203. }
  204. public void For (CodeExpression initExp, CodeExpression conditionExp, CodeExpression nextExp)
  205. {
  206. currentBlock.Add (new CodeFor (initExp, conditionExp, nextExp));
  207. PushNewBlock ();
  208. }
  209. public void EndFor ()
  210. {
  211. CodeBlock block = PopBlock ();
  212. CodeFor cif = currentBlock.GetLastItem () as CodeFor;
  213. if (cif == null || cif.ForBlock != null)
  214. throw new InvalidOperationException ("'EndFor' not allowed here");
  215. cif.ForBlock = block;
  216. }
  217. public void Call (CodeExpression target, string name, params CodeExpression[] parameters)
  218. {
  219. if ((object) target == null)
  220. throw new ArgumentNullException ("target");
  221. if (name == null)
  222. throw new ArgumentNullException ("name");
  223. currentBlock.Add (new CodeMethodCall (target, name, parameters));
  224. }
  225. public void Call (CodeExpression target, MethodBase method, params CodeExpression[] parameters)
  226. {
  227. if ((object) target == null)
  228. throw new ArgumentNullException ("target");
  229. if (method == null)
  230. throw new ArgumentNullException ("method");
  231. currentBlock.Add (new CodeMethodCall (target, method, parameters));
  232. }
  233. public void Call (CodeExpression target, CodeMethod method, params CodeExpression[] parameters)
  234. {
  235. if ((object) target == null)
  236. throw new ArgumentNullException ("target");
  237. if (method == null)
  238. throw new ArgumentNullException ("method");
  239. currentBlock.Add (new CodeMethodCall (target, method, parameters));
  240. }
  241. public void Call (Type type, string name, params CodeExpression[] parameters)
  242. {
  243. if (type == null)
  244. throw new ArgumentNullException ("type");
  245. if (name == null)
  246. throw new ArgumentNullException ("name");
  247. currentBlock.Add (new CodeMethodCall (type, name, parameters));
  248. }
  249. public void Call (MethodInfo method, params CodeExpression[] parameters)
  250. {
  251. if (method == null)
  252. throw new ArgumentNullException ("method");
  253. currentBlock.Add (new CodeMethodCall (method, parameters));
  254. }
  255. public void Call (CodeMethod method, params CodeExpression[] parameters)
  256. {
  257. if ((object) method == null)
  258. throw new ArgumentNullException ("method");
  259. currentBlock.Add (new CodeMethodCall (method, parameters));
  260. }
  261. public CodeExpression CallFunc (CodeExpression target, string name, params CodeExpression[] parameters)
  262. {
  263. if ((object) target == null)
  264. throw new ArgumentNullException ("target");
  265. if (name == null)
  266. throw new ArgumentNullException ("name");
  267. return new CodeMethodCall (target, name, parameters);
  268. }
  269. public CodeExpression CallFunc (CodeExpression target, MethodInfo method, params CodeExpression[] parameters)
  270. {
  271. if ((object) target == null)
  272. throw new ArgumentNullException ("target");
  273. if (method == null)
  274. throw new ArgumentNullException ("method");
  275. return new CodeMethodCall (target, method, parameters);
  276. }
  277. public CodeExpression CallFunc (CodeExpression target, CodeMethod method, params CodeExpression[] parameters)
  278. {
  279. if ((object) target == null)
  280. throw new ArgumentNullException ("target");
  281. if (method == null)
  282. throw new ArgumentNullException ("method");
  283. return new CodeMethodCall (target, method, parameters);
  284. }
  285. public CodeExpression CallFunc (Type type, string name, params CodeExpression[] parameters)
  286. {
  287. if (type == null)
  288. throw new ArgumentNullException ("type");
  289. if (name == null)
  290. throw new ArgumentNullException ("name");
  291. return new CodeMethodCall (type, name, parameters);
  292. }
  293. public CodeExpression CallFunc (MethodInfo method, params CodeExpression[] parameters)
  294. {
  295. if (method == null)
  296. throw new ArgumentNullException ("method");
  297. return new CodeMethodCall (method, parameters);
  298. }
  299. public CodeExpression CallFunc (CodeMethod method, params CodeExpression[] parameters)
  300. {
  301. if ((object) method == null)
  302. throw new ArgumentNullException ("method");
  303. return new CodeMethodCall (method, parameters);
  304. }
  305. public void Inc (CodeValueReference val)
  306. {
  307. Assign (val, new CodeIncrement (val));
  308. }
  309. public void Dec (CodeValueReference val)
  310. {
  311. Assign (val, new CodeDecrement (val));
  312. }
  313. public CodeExpression When (CodeExpression condition, CodeExpression trueResult, CodeExpression falseResult)
  314. {
  315. return new CodeWhen (condition, trueResult, falseResult);
  316. }
  317. public void ConsoleWriteLine (params CodeExpression[] parameters)
  318. {
  319. Call (typeof(Console), "WriteLine", parameters);
  320. }
  321. public void ConsoleWriteLine (params object[] parameters)
  322. {
  323. CodeExpression[] exps = new CodeExpression [parameters.Length];
  324. for (int n=0; n<exps.Length; n++)
  325. exps[n] = Exp.Literal (parameters[n]);
  326. ConsoleWriteLine (exps);
  327. }
  328. public void Return (CodeExpression exp)
  329. {
  330. currentBlock.Add (new CodeReturn (this, exp));
  331. }
  332. public void Return ()
  333. {
  334. currentBlock.Add (new CodeReturn (this));
  335. }
  336. public static CodeBuilder operator+(CodeBuilder cb, CodeItem e)
  337. {
  338. cb.currentBlock.Add (e);
  339. return cb;
  340. }
  341. internal Label ReturnLabel
  342. {
  343. get { return returnLabel; }
  344. set { returnLabel = value; }
  345. }
  346. void PushNewBlock ()
  347. {
  348. blockStack.Push (currentBlock);
  349. currentBlock = new CodeBlock ();
  350. }
  351. CodeBlock PopBlock ()
  352. {
  353. CodeBlock block = currentBlock;
  354. currentBlock = (CodeBlock) blockStack.Pop ();
  355. return block;
  356. }
  357. }
  358. }
  359. #endif