PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Languages/Ruby/Ruby/Compiler/Generation/RubyTypeDispenser.cs

#
C# | 153 lines | 116 code | 21 blank | 16 comment | 9 complexity | f6d2e256e588bab32103b243218e4427 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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. * ironruby@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.Diagnostics;
  18. using System.Reflection.Emit;
  19. using System.Text;
  20. using System.Threading;
  21. using Microsoft.Scripting;
  22. using Microsoft.Scripting.Generation;
  23. using Microsoft.Scripting.Utils;
  24. using IronRuby.Builtins;
  25. using IronRuby.Runtime;
  26. using System.Globalization;
  27. namespace IronRuby.Compiler.Generation {
  28. internal static class RubyTypeDispenser {
  29. private static readonly Publisher<TypeDescription/*!*/, Type/*!*/>/*!*/ _newTypes;
  30. private static readonly Dictionary<Type/*!*/, IList<ITypeFeature/*!*/>/*!*/>/*!*/ _typeFeatures;
  31. private static readonly ITypeFeature/*!*/[]/*!*/ _defaultFeatures = new ITypeFeature[2] {
  32. RubyTypeBuilder.Feature,
  33. InterfacesBuilder.MakeFeature(Type.EmptyTypes)
  34. };
  35. static RubyTypeDispenser() {
  36. _newTypes = new Publisher<TypeDescription, Type>();
  37. _typeFeatures = new Dictionary<Type, IList<ITypeFeature>>();
  38. AddBuiltinType(typeof(object), typeof(RubyObject), false);
  39. AddBuiltinType(typeof(MutableString), typeof(MutableString.Subclass), true);
  40. AddBuiltinType(typeof(Proc), typeof(Proc.Subclass), true);
  41. AddBuiltinType(typeof(RubyRegex), typeof(RubyRegex.Subclass), true);
  42. AddBuiltinType(typeof(Range), typeof(Range.Subclass), true);
  43. AddBuiltinType(typeof(Hash), typeof(Hash.Subclass), true);
  44. AddBuiltinType(typeof(RubyArray), typeof(RubyArray.Subclass), true);
  45. AddBuiltinType(typeof(MatchData), typeof(MatchData.Subclass), true);
  46. AddBuiltinType(typeof(RubyIO), typeof(RubyIO.Subclass), true);
  47. }
  48. internal static Type/*!*/ GetOrCreateType(Type/*!*/ baseType, IList<Type/*!*/>/*!*/ interfaces, bool noOverrides) {
  49. Assert.NotNull(baseType);
  50. Assert.NotNull(interfaces);
  51. ITypeFeature[] features;
  52. if (interfaces.Count == 0) {
  53. features = _defaultFeatures;
  54. } else {
  55. features = new ITypeFeature[2] {
  56. RubyTypeBuilder.Feature,
  57. InterfacesBuilder.MakeFeature(interfaces)
  58. };
  59. }
  60. noOverrides |= typeof(IRubyType).IsAssignableFrom(baseType);
  61. TypeDescription typeInfo = new TypeDescription(baseType, features, noOverrides);
  62. Type type = _newTypes.GetOrCreateValue(typeInfo,
  63. delegate() {
  64. if (TypeImplementsFeatures(baseType, features)) {
  65. return baseType;
  66. }
  67. return CreateType(typeInfo);
  68. });
  69. Debug.Assert(typeof(IRubyObject).IsAssignableFrom(type));
  70. return type;
  71. }
  72. internal static bool TryGetFeatures(Type/*!*/ type, out IList<ITypeFeature/*!*/> features) {
  73. lock (_typeFeatures) {
  74. return _typeFeatures.TryGetValue(type, out features);
  75. }
  76. }
  77. private static bool TypeImplementsFeatures(Type/*!*/ type, IList<ITypeFeature/*!*/>/*!*/ features) {
  78. IList<ITypeFeature> featuresFound;
  79. if (TryGetFeatures(type, out featuresFound)) {
  80. return TypeDescription.FeatureSetsMatch(features, featuresFound);
  81. }
  82. foreach (ITypeFeature feature in features) {
  83. if (!feature.IsImplementedBy(type)) {
  84. return false;
  85. }
  86. }
  87. return true;
  88. }
  89. private static Type CreateType(TypeDescription/*!*/ typeInfo) {
  90. Type baseType = typeInfo.BaseType;
  91. if (baseType.IsSealed) {
  92. throw new NotSupportedException(
  93. String.Format(CultureInfo.InvariantCulture, "Can't inherit from a sealed type {0}.",
  94. RubyContext.GetQualifiedNameNoLock(baseType, null, false))
  95. );
  96. }
  97. string typeName = GetName(baseType);
  98. TypeBuilder tb = Snippets.Shared.DefinePublicType(typeName, baseType);
  99. Utils.Log(typeName, "TYPE_BUILDER");
  100. IFeatureBuilder[] features = new IFeatureBuilder[typeInfo.Features.Count];
  101. RubyTypeEmitter emitter = new RubyTypeEmitter(tb);
  102. for (int i = 0; i < typeInfo.Features.Count; i++) {
  103. features[i] = typeInfo.Features[i].MakeBuilder(tb);
  104. }
  105. foreach (IFeatureBuilder feature in features) {
  106. feature.Implement(emitter);
  107. }
  108. if (!typeInfo.NoOverrides) {
  109. emitter.OverrideMethods(baseType);
  110. }
  111. Type result = emitter.FinishType();
  112. lock (_typeFeatures) {
  113. _typeFeatures.Add(result, typeInfo.Features);
  114. }
  115. return result;
  116. }
  117. private static string GetName(Type/*!*/ baseType) {
  118. // DLR appends a counter, so we don't need to
  119. // TODO: Reflect feature set in the name?
  120. StringBuilder name = new StringBuilder("IronRuby.Classes.");
  121. name.Append(baseType.Name);
  122. return name.ToString();
  123. }
  124. private static void AddBuiltinType(Type/*!*/ clsBaseType, Type/*!*/ rubyType, bool noOverrides) {
  125. AddBuiltinType(clsBaseType, rubyType, _defaultFeatures, noOverrides);
  126. }
  127. private static void AddBuiltinType(Type/*!*/ clsBaseType, Type/*!*/ rubyType, ITypeFeature/*!*/[]/*!*/ features, bool noOverrides) {
  128. _newTypes.GetOrCreateValue(new TypeDescription(clsBaseType, features, noOverrides), () => rubyType);
  129. _typeFeatures[rubyType] = features;
  130. }
  131. }
  132. }