PageRenderTime 35ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/Microsoft.Scripting/Actions/Calls/KeywordConstructorReturnBuilder.cs

https://bitbucket.org/stefanrusek/xronos
C# | 142 lines | 109 code | 14 blank | 19 comment | 10 complexity | 8cc64fcb33727cee91c56cb72aa3b247 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. #if CODEPLEX_40
  16. using System;
  17. #else
  18. using System; using Microsoft;
  19. #endif
  20. using System.Collections.Generic;
  21. #if CODEPLEX_40
  22. using System.Linq.Expressions;
  23. #else
  24. using Microsoft.Linq.Expressions;
  25. #endif
  26. using System.Reflection;
  27. using Microsoft.Scripting.Runtime;
  28. using AstUtils = Microsoft.Scripting.Ast.Utils;
  29. namespace Microsoft.Scripting.Actions.Calls {
  30. #if CODEPLEX_40
  31. using Ast = System.Linq.Expressions.Expression;
  32. #else
  33. using Ast = Microsoft.Linq.Expressions.Expression;
  34. #endif
  35. /// <summary>
  36. /// Updates fields/properties of the returned value with unused keyword parameters.
  37. /// </summary>
  38. class KeywordConstructorReturnBuilder : ReturnBuilder {
  39. private readonly ReturnBuilder _builder;
  40. private readonly int _kwArgCount;
  41. private readonly int[] _indexesUsed;
  42. private readonly MemberInfo[] _membersSet;
  43. private readonly bool _privateBinding;
  44. public KeywordConstructorReturnBuilder(ReturnBuilder builder, int kwArgCount, int[] indexesUsed, MemberInfo[] membersSet,
  45. bool privateBinding)
  46. : base(builder.ReturnType) {
  47. _builder = builder;
  48. _kwArgCount = kwArgCount;
  49. _indexesUsed = indexesUsed;
  50. _membersSet = membersSet;
  51. _privateBinding = privateBinding;
  52. }
  53. internal override Expression ToExpression(ParameterBinder parameterBinder, IList<ArgBuilder> args, IList<Expression> parameters, Expression ret) {
  54. List<Expression> sets = new List<Expression>();
  55. ParameterExpression tmp = parameterBinder.GetTemporary(ret.Type, "val");
  56. sets.Add(
  57. Ast.Assign(tmp, ret)
  58. );
  59. for (int i = 0; i < _indexesUsed.Length; i++) {
  60. Expression value = parameters[parameters.Count - _kwArgCount + _indexesUsed[i]];
  61. switch(_membersSet[i].MemberType) {
  62. case MemberTypes.Field:
  63. FieldInfo fi = (FieldInfo)_membersSet[i];
  64. if (!fi.IsLiteral && !fi.IsInitOnly) {
  65. sets.Add(
  66. Ast.Assign(
  67. Ast.Field(tmp, fi),
  68. ConvertToHelper(parameterBinder, value, fi.FieldType)
  69. )
  70. );
  71. } else {
  72. // call a helper which throws the error but "returns object"
  73. sets.Add(
  74. Ast.Convert(
  75. Ast.Call(
  76. typeof(ScriptingRuntimeHelpers).GetMethod("ReadOnlyAssignError"),
  77. AstUtils.Constant(true),
  78. AstUtils.Constant(fi.Name)
  79. ),
  80. fi.FieldType
  81. )
  82. );
  83. }
  84. break;
  85. case MemberTypes.Property:
  86. PropertyInfo pi = (PropertyInfo)_membersSet[i];
  87. if (pi.GetSetMethod(_privateBinding) != null) {
  88. sets.Add(
  89. Ast.Assign(
  90. Ast.Property(tmp, pi),
  91. ConvertToHelper(parameterBinder, value, pi.PropertyType)
  92. )
  93. );
  94. } else {
  95. // call a helper which throws the error but "returns object"
  96. sets.Add(
  97. Ast.Convert(
  98. Ast.Call(
  99. typeof(ScriptingRuntimeHelpers).GetMethod("ReadOnlyAssignError"),
  100. AstUtils.Constant(false),
  101. AstUtils.Constant(pi.Name)
  102. ),
  103. pi.PropertyType
  104. )
  105. );
  106. }
  107. break;
  108. }
  109. }
  110. sets.Add(
  111. tmp
  112. );
  113. Expression newCall = Ast.Block(
  114. sets.ToArray()
  115. );
  116. return _builder.ToExpression(parameterBinder, args, parameters, newCall);
  117. }
  118. private static Expression ConvertToHelper(ParameterBinder parameterBinder, Expression value, Type type) {
  119. if (type == value.Type) {
  120. return value;
  121. }
  122. if (type.IsAssignableFrom(value.Type)) {
  123. return AstUtils.Convert(value, type);
  124. }
  125. return parameterBinder.GetDynamicConversion(value, type);
  126. }
  127. }
  128. }