PageRenderTime 4137ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/DLR_Main/Languages/IronPython/IronPython/Compiler/Ast/Comprehension.cs

https://bitbucket.org/mdavid/dlr
C# | 256 lines | 196 code | 43 blank | 17 comment | 18 complexity | 23a81f22314c599046c037b404beb6eb MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Reflection;
  18. using Microsoft.Scripting;
  19. using IronPython.Runtime;
  20. #if !CLR2
  21. using MSAst = System.Linq.Expressions;
  22. #else
  23. using MSAst = Microsoft.Scripting.Ast;
  24. #endif
  25. using AstUtils = Microsoft.Scripting.Ast.Utils;
  26. namespace IronPython.Compiler.Ast {
  27. using Ast = MSAst.Expression;
  28. public abstract class ComprehensionIterator : Node {
  29. internal abstract MSAst.Expression Transform(MSAst.Expression body);
  30. }
  31. public abstract class Comprehension : Expression {
  32. public abstract IList<ComprehensionIterator> Iterators { get; }
  33. public abstract override string NodeName { get; }
  34. protected abstract MSAst.ParameterExpression MakeParameter();
  35. protected abstract MethodInfo Factory();
  36. protected abstract MSAst.Expression Body(MSAst.ParameterExpression res);
  37. public abstract override void Walk(PythonWalker walker);
  38. public override Ast Reduce() {
  39. MSAst.ParameterExpression res = MakeParameter();
  40. // 1. Initialization code - create list and store it in the temp variable
  41. MSAst.Expression initialize =
  42. Ast.Assign(
  43. res,
  44. Ast.Call(Factory())
  45. );
  46. // 2. Create body from LHS: res.Append(item), res.Add(key, value), etc.
  47. MSAst.Expression body = Body(res);
  48. // 3. Transform all iterators in reverse order, building the true bodies
  49. for (int current = Iterators.Count - 1; current >= 0; current--) {
  50. ComprehensionIterator iterator = Iterators[current];
  51. body = iterator.Transform(body);
  52. }
  53. return Ast.Block(
  54. new[] { res },
  55. initialize,
  56. body,
  57. res
  58. );
  59. }
  60. }
  61. public sealed class ListComprehension : Comprehension {
  62. private readonly ComprehensionIterator[] _iterators;
  63. private readonly Expression _item;
  64. public ListComprehension(Expression item, ComprehensionIterator[] iterators) {
  65. _item = item;
  66. _iterators = iterators;
  67. }
  68. public Expression Item {
  69. get { return _item; }
  70. }
  71. public override IList<ComprehensionIterator> Iterators {
  72. get { return _iterators; }
  73. }
  74. protected override MSAst.ParameterExpression MakeParameter() {
  75. return Ast.Parameter(typeof(List), "list_comprehension_list");
  76. }
  77. protected override MethodInfo Factory() {
  78. return AstMethods.MakeList;
  79. }
  80. protected override Ast Body(MSAst.ParameterExpression res) {
  81. return GlobalParent.AddDebugInfo(
  82. Ast.Call(
  83. AstMethods.ListAddForComprehension,
  84. res,
  85. AstUtils.Convert(_item, typeof(object))
  86. ),
  87. _item.Span
  88. );
  89. }
  90. public override string NodeName {
  91. get {
  92. return "list comprehension";
  93. }
  94. }
  95. public override void Walk(PythonWalker walker) {
  96. if (walker.Walk(this)) {
  97. if (_item != null) {
  98. _item.Walk(walker);
  99. }
  100. if (_iterators != null) {
  101. foreach (ComprehensionIterator ci in _iterators) {
  102. ci.Walk(walker);
  103. }
  104. }
  105. }
  106. walker.PostWalk(this);
  107. }
  108. }
  109. public sealed class SetComprehension : Comprehension {
  110. private readonly ComprehensionIterator[] _iterators;
  111. private readonly Expression _item;
  112. public SetComprehension(Expression item, ComprehensionIterator[] iterators) {
  113. _item = item;
  114. _iterators = iterators;
  115. }
  116. public Expression Item {
  117. get { return _item; }
  118. }
  119. public override IList<ComprehensionIterator> Iterators {
  120. get { return _iterators; }
  121. }
  122. protected override MSAst.ParameterExpression MakeParameter() {
  123. return Ast.Parameter(typeof(SetCollection), "set_comprehension_set");
  124. }
  125. protected override MethodInfo Factory() {
  126. return AstMethods.MakeEmptySet;
  127. }
  128. protected override Ast Body(MSAst.ParameterExpression res) {
  129. return GlobalParent.AddDebugInfo(
  130. Ast.Call(
  131. AstMethods.SetAddForComprehension,
  132. res,
  133. AstUtils.Convert(_item, typeof(object))
  134. ),
  135. _item.Span
  136. );
  137. }
  138. public override string NodeName {
  139. get {
  140. return "set comprehension";
  141. }
  142. }
  143. public override void Walk(PythonWalker walker) {
  144. if (walker.Walk(this)) {
  145. if (_item != null) {
  146. _item.Walk(walker);
  147. }
  148. if (_iterators != null) {
  149. foreach (ComprehensionIterator ci in _iterators) {
  150. ci.Walk(walker);
  151. }
  152. }
  153. }
  154. walker.PostWalk(this);
  155. }
  156. }
  157. public sealed class DictionaryComprehension : Comprehension {
  158. private readonly ComprehensionIterator[] _iterators;
  159. private readonly Expression _key, _value;
  160. public DictionaryComprehension(Expression key, Expression value, ComprehensionIterator[] iterators) {
  161. _key = key;
  162. _value = value;
  163. _iterators = iterators;
  164. }
  165. public Expression Key {
  166. get { return _key; }
  167. }
  168. public Expression Value {
  169. get { return _value; }
  170. }
  171. public override IList<ComprehensionIterator> Iterators {
  172. get { return _iterators; }
  173. }
  174. protected override MSAst.ParameterExpression MakeParameter() {
  175. return Ast.Parameter(typeof(PythonDictionary), "dict_comprehension_dict");
  176. }
  177. protected override MethodInfo Factory() {
  178. return AstMethods.MakeEmptyDict;
  179. }
  180. protected override Ast Body(MSAst.ParameterExpression res) {
  181. return GlobalParent.AddDebugInfo(
  182. Ast.Call(
  183. AstMethods.DictAddForComprehension,
  184. res,
  185. AstUtils.Convert(_key, typeof(object)),
  186. AstUtils.Convert(_value, typeof(object))
  187. ),
  188. new SourceSpan(_key.Span.Start, _value.Span.End)
  189. );
  190. }
  191. public override string NodeName {
  192. get {
  193. return "dict comprehension";
  194. }
  195. }
  196. public override void Walk(PythonWalker walker) {
  197. if (walker.Walk(this)) {
  198. if (_key != null) {
  199. _key.Walk(walker);
  200. }
  201. if (_value != null) {
  202. _value.Walk(walker);
  203. }
  204. if (_iterators != null) {
  205. foreach (ComprehensionIterator ci in _iterators) {
  206. ci.Walk(walker);
  207. }
  208. }
  209. }
  210. walker.PostWalk(this);
  211. }
  212. }
  213. }