PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/DICK.B1/IronPython/Runtime/ModuleDictionaryStorage.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 211 lines | 156 code | 32 blank | 23 comment | 33 complexity | e0eb913bef333bc047ea3a496db4c866 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;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using System.Reflection;
  19. using IronPython.Runtime.Types;
  20. using Microsoft.Scripting;
  21. using Microsoft.Scripting.Actions;
  22. using Microsoft.Scripting.Runtime;
  23. using Microsoft.Scripting.Utils;
  24. namespace IronPython.Runtime {
  25. /// <summary>
  26. /// Enables lazy initialization of module dictionaries.
  27. /// </summary>
  28. class ModuleDictionaryStorage : StringDictionaryStorage {
  29. private Type/*!*/ _type;
  30. private bool _cleared;
  31. public ModuleDictionaryStorage(Type/*!*/ moduleType) {
  32. Debug.Assert(moduleType != null);
  33. _type = moduleType;
  34. }
  35. public override bool Remove(object key) {
  36. string strKey = key as string;
  37. if (strKey == null) {
  38. return base.Remove(key);
  39. }
  40. bool found = base.Remove(key);
  41. object value;
  42. if (TryGetLazyValue(strKey, out value)) {
  43. // hide the deleted value
  44. base.Add(key, Uninitialized.Instance);
  45. found = true;
  46. }
  47. return found;
  48. }
  49. protected virtual void LazyAdd(object name, object value) {
  50. Add(name, value);
  51. }
  52. public override bool Contains(object key) {
  53. object dummy;
  54. return TryGetValue(key, out dummy);
  55. }
  56. public override void Clear() {
  57. _cleared = true;
  58. base.Clear();
  59. }
  60. public override List<KeyValuePair<object, object>> GetItems() {
  61. List<KeyValuePair<object, object>> res = new List<KeyValuePair<object, object>>();
  62. foreach (KeyValuePair<object, object> kvp in base.GetItems()) {
  63. if (kvp.Value != Uninitialized.Instance) {
  64. res.Add(kvp);
  65. }
  66. }
  67. MemberInfo[] members = _type.GetMembers();
  68. foreach (MemberInfo mi in members) {
  69. if (base.Contains(mi.Name)) continue;
  70. object value;
  71. if (TryGetLazyValue(mi.Name, out value)) {
  72. res.Add(new KeyValuePair<object, object>(mi.Name, value));
  73. }
  74. }
  75. return res;
  76. }
  77. public override int Count {
  78. get {
  79. // need to ensure we're fully populated
  80. GetItems();
  81. return base.Count;
  82. }
  83. }
  84. private bool TryGetLazyValue(string name, out object value) {
  85. return TryGetLazyValue(name, true, out value);
  86. }
  87. private bool TryGetLazyValue(string name, bool publish, out object value) {
  88. if (!_cleared) {
  89. MemberInfo[] members = NonHiddenMembers(GetMember(name));
  90. if (members.Length > 0) {
  91. // we only support fields, methods, and nested types in modules.
  92. switch (members[0].MemberType) {
  93. case MemberTypes.Field:
  94. Debug.Assert(members.Length == 1);
  95. value = ((FieldInfo)members[0]).GetValue(null);
  96. if (publish) {
  97. LazyAdd(name, value);
  98. }
  99. return true;
  100. case MemberTypes.Method:
  101. if (!((MethodInfo)members[0]).IsSpecialName) {
  102. value = BuiltinFunction.MakeFunction(
  103. name,
  104. ArrayUtils.ConvertAll<MemberInfo, MethodInfo>(members, delegate(MemberInfo mi) { return (MethodInfo)mi; }),
  105. members[0].DeclaringType
  106. );
  107. if (publish) {
  108. LazyAdd(name, value);
  109. }
  110. return true;
  111. }
  112. break;
  113. case MemberTypes.Property:
  114. Debug.Assert(members.Length == 1);
  115. value = ((PropertyInfo)members[0]).GetValue(null, ArrayUtils.EmptyObjects);
  116. if (publish) {
  117. LazyAdd(name, value);
  118. }
  119. return true;
  120. case MemberTypes.NestedType:
  121. if (members.Length == 1) {
  122. value = DynamicHelpers.GetPythonTypeFromType((Type)members[0]);
  123. } else {
  124. TypeTracker tt = (TypeTracker)MemberTracker.FromMemberInfo(members[0]);
  125. for (int i = 1; i < members.Length; i++) {
  126. tt = TypeGroup.UpdateTypeEntity(tt, (TypeTracker)MemberTracker.FromMemberInfo(members[i]));
  127. }
  128. value = tt;
  129. }
  130. if (publish) {
  131. LazyAdd(name, value);
  132. }
  133. return true;
  134. }
  135. }
  136. }
  137. value = null;
  138. return false;
  139. }
  140. private static MemberInfo[] NonHiddenMembers(MemberInfo[] members) {
  141. List<MemberInfo> res = new List<MemberInfo>(members.Length);
  142. foreach (MemberInfo t in members) {
  143. if (t.IsDefined(typeof(PythonHiddenAttribute), false)) {
  144. continue;
  145. }
  146. res.Add(t);
  147. }
  148. return res.ToArray();
  149. }
  150. private MemberInfo[] GetMember(string name) {
  151. return _type.GetMember(name, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
  152. }
  153. public override bool TryGetValue(object key, out object value) {
  154. if (base.TryGetValue(key, out value)) {
  155. return value != Uninitialized.Instance;
  156. }
  157. string strKey = key as string;
  158. if(strKey != null) {
  159. return TryGetLazyValue(strKey, out value);
  160. }
  161. return false;
  162. }
  163. public virtual void Reload() {
  164. foreach (KeyValuePair<object, object> kvp in base.GetItems()) {
  165. if (kvp.Value == Uninitialized.Instance) {
  166. // hiding a member
  167. base.Remove(kvp.Key);
  168. } else {
  169. // member exists, need to remove it from the base class
  170. // in case it differs from the member we actually have.
  171. string strKey = kvp.Key as string;
  172. if (strKey != null && GetMember(strKey).Length > 0) {
  173. base.Remove(kvp.Key);
  174. }
  175. }
  176. }
  177. }
  178. }
  179. }