/src/IronLua/IronLua/Ast/LuaPrinter.cs

http://ironlua.googlecode.com/ · C# · 429 lines · 366 code · 63 blank · 0 comment · 17 complexity · 2aa490d57e8b9506c4315a131626dda2 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.IO;
  5. using Dlr = Microsoft.Scripting;
  6. namespace IronLua.Ast {
  7. public class LuaPrinter : BaseAstVisitor {
  8. public static void PrintCode (TextWriter writer, LuaNode node)
  9. {
  10. var printer = new LuaPrinter (writer);
  11. node.Accept (printer);
  12. }
  13. public static string ToCodeString (LuaNode node)
  14. {
  15. var writer = new StringWriter ();
  16. PrintCode (writer, node);
  17. return writer.ToString ();
  18. }
  19. const string ListSeparator = ", ";
  20. TextWriter writer;
  21. bool write_indent;
  22. int indent;
  23. private LuaPrinter (TextWriter writer)
  24. {
  25. this.writer = writer;
  26. }
  27. void WriteIndent ()
  28. {
  29. if (!write_indent)
  30. return;
  31. for (int i = 0; i < indent; i++)
  32. writer.Write ("\t");
  33. }
  34. void Write (object o)
  35. {
  36. WriteIndent ();
  37. writer.Write (o);
  38. write_indent = false;
  39. }
  40. void Write (string s)
  41. {
  42. WriteIndent ();
  43. writer.Write (s);
  44. write_indent = false;
  45. }
  46. void Write (string s, params object [] objs)
  47. {
  48. WriteIndent ();
  49. writer.Write (s, objs);
  50. write_indent = false;
  51. }
  52. void WriteLine ()
  53. {
  54. writer.WriteLine ();
  55. write_indent = true;
  56. }
  57. void WriteLine (string s)
  58. {
  59. WriteIndent ();
  60. writer.WriteLine (s);
  61. write_indent = true;
  62. }
  63. void WriteLine (string s, params object [] objs)
  64. {
  65. WriteIndent ();
  66. writer.WriteLine (s, objs);
  67. write_indent = true;
  68. }
  69. void Indent ()
  70. {
  71. indent++;
  72. write_indent = true;
  73. }
  74. void Dedent ()
  75. {
  76. indent--;
  77. }
  78. void WriteIndented (Action action)
  79. {
  80. Indent ();
  81. action ();
  82. Dedent ();
  83. }
  84. void WriteDoBlock (Action action)
  85. {
  86. WriteLine ("do");
  87. WriteIndented (action);
  88. WriteLine ("end");
  89. }
  90. void WriteBetweenSpaces (Action action)
  91. {
  92. Write (" ");
  93. action ();
  94. Write (" ");
  95. }
  96. void WriteBetweenSpaces (string s)
  97. {
  98. Write (" ");
  99. Write (s);
  100. Write (" ");
  101. }
  102. void WriteBetweenParenthesis (Action action)
  103. {
  104. Write ("(");
  105. action ();
  106. Write (")");
  107. }
  108. void WriteBetweenBrackets (Action action)
  109. {
  110. Write ("[");
  111. action ();
  112. Write ("]");
  113. }
  114. void WriteSpace ()
  115. {
  116. Write (" ");
  117. }
  118. void VisitList<TElement> (IEnumerable<TElement> list, string separator) where TElement : LuaNode
  119. {
  120. int i = 0;
  121. foreach (var e in list) {
  122. if (i > 0)
  123. Write (separator);
  124. e.Accept (this);
  125. i++;
  126. }
  127. }
  128. public override void VisitList<TElement> (IEnumerable<TElement> list)
  129. {
  130. VisitList (list, ListSeparator);
  131. }
  132. public override void VisitBlockStatement (BlockStatement node)
  133. {
  134. VisitList (node.Statements, string.Empty);
  135. }
  136. public override void VisitAssignStatement (AssignStatement node)
  137. {
  138. VisitList (node.Left);
  139. WriteBetweenSpaces ("=");
  140. VisitList (node.Right);
  141. WriteLine ();
  142. }
  143. public override void VisitDoStatement (DoStatement node)
  144. {
  145. WriteDoBlock (() => node.Body.Accept (this));
  146. }
  147. public override void VisitWhileStatement (WhileStatement node)
  148. {
  149. Write ("while");
  150. WriteBetweenSpaces (() => node.Condition.Accept (this));
  151. WriteDoBlock (() => node.Body.Accept (this));
  152. }
  153. public override void VisitRepeatStatement (RepeatStatement node)
  154. {
  155. WriteLine ("repeat");
  156. WriteIndented (() => node.Body.Accept (this));
  157. Write ("until");
  158. WriteSpace ();
  159. node.Until.Accept (this);
  160. WriteLine ();
  161. }
  162. public override void VisitIfStatement (IfStatement node)
  163. {
  164. Write ("if");
  165. WriteBetweenSpaces (() => node.Condition.Accept (this));
  166. WriteLine ("then");
  167. WriteIndented (() => node.Then.Accept (this));
  168. VisitList (node.ElseIfs, string.Empty);
  169. if (node.Else != null) {
  170. WriteLine ("else");
  171. WriteIndented (() => node.Else.Accept (this));
  172. }
  173. WriteLine ("end");
  174. }
  175. public override void VisitElseIfClause (ElseIfClause node)
  176. {
  177. Write ("elseif");
  178. WriteBetweenSpaces (() => node.Condition.Accept (this));
  179. WriteLine ("then");
  180. WriteIndented (() => node.Then.Accept (this));
  181. }
  182. public override void VisitReturnStatement (ReturnStatement node)
  183. {
  184. Write ("return");
  185. WriteSpace ();
  186. VisitList (node.Expressions);
  187. WriteLine ();
  188. }
  189. public override void VisitBreakStatement (BreakStatement node)
  190. {
  191. WriteLine ("break");
  192. }
  193. public override void VisitExpressionStatement (ExpressionStatement node)
  194. {
  195. node.Expression.Accept (this);
  196. WriteLine ();
  197. }
  198. public override void VisitCommentStatement (CommentStatement node)
  199. {
  200. Write ("--");
  201. WriteSpace ();
  202. WriteLine (node.Comment);
  203. }
  204. public override void VisitForStatement (ForStatement node)
  205. {
  206. Write ("for");
  207. WriteBetweenSpaces (() => node.Variable.Accept (this));
  208. Write ("=");
  209. WriteSpace ();
  210. node.Initializer.Accept (this);
  211. Write (ListSeparator);
  212. node.Limit.Accept (this);
  213. if (node.Step != null) {
  214. Write (ListSeparator);
  215. node.Step.Accept (this);
  216. }
  217. WriteSpace ();
  218. WriteDoBlock (() => node.Body.Accept (this));
  219. }
  220. public override void VisitForEachStatement (ForEachStatement node)
  221. {
  222. Write ("for");
  223. WriteBetweenSpaces (() => VisitList (node.Variables));
  224. Write ("in");
  225. WriteBetweenSpaces (() => VisitList (node.Expressions));
  226. WriteDoBlock (() => node.Body.Accept (this));
  227. }
  228. public override void VisitLocalStatement (LocalStatement node)
  229. {
  230. Write ("local");
  231. WriteBetweenSpaces (() => VisitList (node.Variables));
  232. Write ("=");
  233. WriteSpace ();
  234. VisitList (node.Expressions);
  235. WriteLine ();
  236. }
  237. static string OperatorToString (UnaryOperatorType op)
  238. {
  239. switch (op) {
  240. case UnaryOperatorType.Length:
  241. return "#";
  242. case UnaryOperatorType.Negation:
  243. return "-";
  244. case UnaryOperatorType.Not:
  245. return "not";
  246. default:
  247. throw new NotSupportedException ();
  248. }
  249. }
  250. public override void VisitUnaryExpression (UnaryExpression node)
  251. {
  252. Write (OperatorToString (node.Operator));
  253. WriteBetweenParenthesis (() => node.Expression.Accept (this));
  254. }
  255. static string OperatorToString (BinaryOperatorType op)
  256. {
  257. switch (op) {
  258. case BinaryOperatorType.Add:
  259. return "+";
  260. case BinaryOperatorType.And:
  261. return "and";
  262. case BinaryOperatorType.Divide:
  263. return "/";
  264. case BinaryOperatorType.Equal:
  265. return "==";
  266. case BinaryOperatorType.GreaterThan:
  267. return ">";
  268. case BinaryOperatorType.GreaterThanOrEqual:
  269. return ">=";
  270. case BinaryOperatorType.LessThan:
  271. return "<";
  272. case BinaryOperatorType.LessThanOrEqual:
  273. return "<=";
  274. case BinaryOperatorType.Modulo:
  275. return "%";
  276. case BinaryOperatorType.Multiply:
  277. return "*";
  278. case BinaryOperatorType.NotEqual:
  279. return "~=";
  280. case BinaryOperatorType.Or:
  281. return "or";
  282. case BinaryOperatorType.Power:
  283. return "^";
  284. case BinaryOperatorType.Subtract:
  285. return "-";
  286. case BinaryOperatorType.Concat:
  287. return "..";
  288. default:
  289. throw new InvalidOperationException ();
  290. }
  291. }
  292. public override void VisitBinaryExpression (BinaryExpression node)
  293. {
  294. WriteBetweenParenthesis (() => {
  295. node.Left.Accept (this);
  296. WriteBetweenSpaces (OperatorToString (node.Operator));
  297. node.Right.Accept (this);
  298. });
  299. }
  300. public override void VisitLiteralExpression (LiteralExpression node)
  301. {
  302. Write (FormatLiteral (node.Value));
  303. }
  304. string FormatLiteral (object obj)
  305. {
  306. if (obj == null)
  307. return "nil";
  308. if (obj == Dlr.Runtime.RuntimeHelpers.True)
  309. return "true";
  310. if (obj == Dlr.Runtime.RuntimeHelpers.False)
  311. return "false";
  312. if (obj is string)
  313. return "\"" + obj + "\"";
  314. if (obj is double)
  315. return ((double) obj).ToString (NumberFormatInfo.InvariantInfo);
  316. return obj.ToString ();
  317. }
  318. public override void VisitTableCreationExpression (TableCreationExpression node)
  319. {
  320. Write ("{}");
  321. }
  322. public override void VisitVariableExpression (VariableExpression node)
  323. {
  324. Write (node.Name);
  325. }
  326. public override void VisitSlotExpression (SlotExpression node)
  327. {
  328. node.Target.Accept (this);
  329. WriteSpace ();
  330. WriteBetweenBrackets (() => node.Expression.Accept (this));
  331. }
  332. public override void VisitMemberExpression (MemberExpression node)
  333. {
  334. node.Target.Accept (this);
  335. Write (".");
  336. Write (node.Name);
  337. }
  338. public override void VisitFunctionCallExpression (FunctionCallExpression node)
  339. {
  340. node.Target.Accept (this);
  341. WriteSpace ();
  342. WriteBetweenParenthesis (() => VisitList (node.Arguments));
  343. }
  344. public override void VisitMethodCallExpression (MethodCallExpression node)
  345. {
  346. node.Target.Accept (this);
  347. Write (":");
  348. Write (node.Name);
  349. WriteSpace ();
  350. WriteBetweenParenthesis (() => VisitList (node.Arguments));
  351. }
  352. public override void VisitFunctionExpression (FunctionExpression node)
  353. {
  354. Write ("function");
  355. WriteSpace ();
  356. WriteBetweenParenthesis (() => VisitList (node.Parameters));
  357. WriteLine ();
  358. WriteIndented (() => node.Body.Accept (this));
  359. Write ("end");
  360. }
  361. public override void VisitVarArgExpression (VarArgExpression node)
  362. {
  363. Write ("...");
  364. }
  365. }
  366. }