PageRenderTime 46ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/DICK.B1/IronPython/Compiler/Ast/SequenceExpression.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 172 lines | 113 code | 28 blank | 31 comment | 9 complexity | 5fc94ba70d458a32fe1d48c24c4e51d4 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System.Collections.Generic;
  16. using System.Collections.ObjectModel;
  17. using System.Runtime.CompilerServices;
  18. using Microsoft.Scripting;
  19. using Microsoft.Scripting.Runtime;
  20. using IronPython.Runtime.Binding;
  21. using IronPython.Runtime.Operations;
  22. #if !CLR2
  23. using MSAst = System.Linq.Expressions;
  24. #else
  25. using MSAst = Microsoft.Scripting.Ast;
  26. #endif
  27. using AstUtils = Microsoft.Scripting.Ast.Utils;
  28. namespace IronPython.Compiler.Ast {
  29. using Ast = MSAst.Expression;
  30. public abstract class SequenceExpression : Expression {
  31. private readonly Expression[] _items;
  32. protected SequenceExpression(Expression[] items) {
  33. _items = items;
  34. }
  35. public IList<Expression> Items {
  36. get { return _items; }
  37. }
  38. internal override MSAst.Expression TransformSet(SourceSpan span, MSAst.Expression right, PythonOperationKind op) {
  39. // if we just have a simple named multi-assignment (e.g. a, b = 1,2)
  40. // then go ahead and step over the entire statement at once. If we have a
  41. // more complex statement (e.g. a.b, c.d = 1, 2) then we'll step over the
  42. // sets individually as they could be property sets the user wants to step
  43. // into. TODO: Enable stepping of the right hand side?
  44. bool emitIndividualSets = false;
  45. foreach (Expression e in _items) {
  46. if (IsComplexAssignment(e)) {
  47. emitIndividualSets = true;
  48. break;
  49. }
  50. }
  51. SourceSpan rightSpan = SourceSpan.None;
  52. SourceSpan leftSpan =
  53. (Span.Start.IsValid && span.IsValid) ?
  54. new SourceSpan(Span.Start, span.End) :
  55. SourceSpan.None;
  56. SourceSpan totalSpan = SourceSpan.None;
  57. if (emitIndividualSets) {
  58. rightSpan = span;
  59. leftSpan = SourceSpan.None;
  60. totalSpan = (Span.Start.IsValid && span.IsValid) ?
  61. new SourceSpan(Span.Start, span.End) :
  62. SourceSpan.None;
  63. }
  64. // 1. Evaluate the expression and assign the value to the temp.
  65. MSAst.ParameterExpression right_temp = Ast.Variable(typeof(object), "unpacking");
  66. // 2. Add the assignment "right_temp = right" into the suite/block
  67. MSAst.Expression assignStmt1 = MakeAssignment(right_temp, right);
  68. // 3. Call GetEnumeratorValues on the right side (stored in temp)
  69. MSAst.Expression enumeratorValues = Ast.Call(
  70. AstMethods.GetEnumeratorValues, // method
  71. // arguments
  72. Parent.LocalContext,
  73. right_temp,
  74. AstUtils.Constant(_items.Length)
  75. );
  76. // 4. Create temporary variable for the array
  77. MSAst.ParameterExpression array_temp = Ast.Variable(typeof(object[]), "array");
  78. // 5. Assign the value of the method call (mce) into the array temp
  79. // And add the assignment "array_temp = Ops.GetEnumeratorValues(...)" into the block
  80. MSAst.Expression assignStmt2 = MakeAssignment(
  81. array_temp,
  82. enumeratorValues,
  83. rightSpan
  84. );
  85. ReadOnlyCollectionBuilder<MSAst.Expression> sets = new ReadOnlyCollectionBuilder<MSAst.Expression>(_items.Length + 1);
  86. for (int i = 0; i < _items.Length; i++) {
  87. // target = array_temp[i]
  88. Expression target = _items[i];
  89. if (target == null) {
  90. continue;
  91. }
  92. // 6. array_temp[i]
  93. MSAst.Expression element = Ast.ArrayAccess(
  94. array_temp, // array expression
  95. AstUtils.Constant(i) // index
  96. );
  97. // 7. target = array_temp[i], and add the transformed assignment into the list of sets
  98. MSAst.Expression set = target.TransformSet(
  99. emitIndividualSets ? // span
  100. target.Span :
  101. SourceSpan.None,
  102. element,
  103. PythonOperationKind.None
  104. );
  105. sets.Add(set);
  106. }
  107. // 9. add the sets as their own block so they can be marked as a single span, if necessary.
  108. sets.Add(AstUtils.Empty());
  109. MSAst.Expression itemSet = GlobalParent.AddDebugInfo(Ast.Block(sets.ToReadOnlyCollection()), leftSpan);
  110. // 10. Return the suite statement (block)
  111. return GlobalParent.AddDebugInfo(Ast.Block(new[] { array_temp, right_temp }, assignStmt1, assignStmt2, itemSet, AstUtils.Empty()), totalSpan);
  112. }
  113. internal override string CheckAssign() {
  114. return null;
  115. }
  116. internal override string CheckDelete() {
  117. return null;
  118. }
  119. internal override string CheckAugmentedAssign() {
  120. return "illegal expression for augmented assignment";
  121. }
  122. private static bool IsComplexAssignment(Expression expr) {
  123. return !(expr is NameExpression);
  124. }
  125. internal override MSAst.Expression TransformDelete() {
  126. MSAst.Expression[] statements = new MSAst.Expression[_items.Length + 1];
  127. for (int i = 0; i < _items.Length; i++) {
  128. statements[i] = _items[i].TransformDelete();
  129. }
  130. statements[_items.Length] = AstUtils.Empty();
  131. return GlobalParent.AddDebugInfo(Ast.Block(statements), Span);
  132. }
  133. internal override bool CanThrow {
  134. get {
  135. foreach (Expression e in _items) {
  136. if (e.CanThrow) {
  137. return true;
  138. }
  139. }
  140. return false;
  141. }
  142. }
  143. }
  144. }