PageRenderTime 53ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/Ruby/Ruby/Runtime/RubyContext.cs

http://github.com/IronLanguages/main
C# | 3085 lines | 2196 code | 574 blank | 315 comment | 400 complexity | 76f7b2770cb8793948b287af4862ca4f MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full 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. * 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. #if FEATURE_CORE_DLR
  16. using MSA = System.Linq.Expressions;
  17. #else
  18. using MSA = Microsoft.Scripting.Ast;
  19. #endif
  20. using System;
  21. using System.Collections.Generic;
  22. using System.Diagnostics;
  23. using System.Dynamic;
  24. using System.IO;
  25. using System.Reflection;
  26. using System.Runtime.CompilerServices;
  27. using System.Security;
  28. using System.Text;
  29. using System.Threading;
  30. using IronRuby.Builtins;
  31. using IronRuby.Compiler;
  32. using IronRuby.Compiler.Ast;
  33. using IronRuby.Compiler.Generation;
  34. using IronRuby.Hosting;
  35. using IronRuby.Runtime.Calls;
  36. using IronRuby.Runtime.Conversions;
  37. using Microsoft.Scripting;
  38. using Microsoft.Scripting.Actions;
  39. using Microsoft.Scripting.Runtime;
  40. using Microsoft.Scripting.Utils;
  41. using System.Collections.ObjectModel;
  42. using System.Globalization;
  43. namespace IronRuby.Runtime {
  44. [ReflectionCached]
  45. public sealed class RubyContext : LanguageContext {
  46. #region Constants
  47. internal static readonly Guid RubyLanguageGuid = new Guid("F03C4640-DABA-473f-96F1-391400714DAB");
  48. private static readonly Guid LanguageVendor_Microsoft = new Guid(-1723120188, -6423, 0x11d2, 0x90, 0x3f, 0, 0xc0, 0x4f, 0xa3, 2, 0xa1);
  49. private static int _RuntimeIdGenerator = 0;
  50. // MRI compliance:
  51. public string/*!*/ MriVersion {
  52. get { return "1.9.2"; }
  53. }
  54. public string/*!*/ StandardLibraryVersion {
  55. get { return "1.9.1"; }
  56. }
  57. public string/*!*/ MriReleaseDate {
  58. get { return "2010-08-18"; }
  59. }
  60. public int MriPatchLevel {
  61. get { return 0; }
  62. }
  63. public const string BinDirEnvironmentVariable = "IRONRUBY_11";
  64. // IronRuby:
  65. public const string IronRubyInformationalVersion = "1.1.3";
  66. #if !SILVERLIGHT
  67. public const string/*!*/ IronRubyVersionString = "1.1.3.0";
  68. public static readonly Version IronRubyVersion = new Version(1, 1, 3, 0);
  69. #else
  70. public const string/*!*/ IronRubyVersionString = "1.1.1302.0";
  71. public static readonly Version IronRubyVersion = new Version(1, 1, 1302, 0);
  72. #endif
  73. internal const string/*!*/ IronRubyDisplayName = "IronRuby";
  74. internal const string/*!*/ IronRubyNames = "IronRuby;Ruby;rb";
  75. internal const string/*!*/ IronRubyFileExtensions = ".rb";
  76. #endregion
  77. // TODO: remove
  78. internal static RubyContext _Default;
  79. private readonly int _runtimeId;
  80. private readonly RubyScope/*!*/ _emptyScope;
  81. private RubyOptions/*!*/ _options;
  82. private readonly TopNamespaceTracker _namespaces;
  83. private readonly Loader/*!*/ _loader;
  84. private readonly Scope/*!*/ _globalScope;
  85. private readonly RubyMetaBinderFactory/*!*/ _metaBinderFactory;
  86. private readonly RubyBinder _binder;
  87. private DynamicDelegateCreator _delegateCreator;
  88. private RubyService _rubyService;
  89. #region Global Variables (thread-safe access)
  90. /// <summary>
  91. /// $0
  92. /// </summary>
  93. public MutableString CommandLineProgramPath { get; set; }
  94. /// <summary>
  95. /// $? of type Process::Status
  96. /// </summary>
  97. [ThreadStatic]
  98. private static object _childProcessExitStatus;
  99. /// <summary>
  100. /// $/, $-O
  101. /// </summary>
  102. private MutableString _inputSeparator;
  103. /// <summary>
  104. /// $\
  105. /// </summary>
  106. private MutableString _outputSeparator;
  107. /// <summary>
  108. /// $;, $-F
  109. /// </summary>
  110. private object _stringSeparator;
  111. /// <summary>
  112. /// $,
  113. /// </summary>
  114. private MutableString _itemSeparator;
  115. private readonly Dictionary<string/*!*/, GlobalVariable>/*!*/ _globalVariables;
  116. public object/*!*/ GlobalVariablesLock { get { return _globalVariables; } }
  117. // not thread safe: use GlobalVariablesLock to synchronize access to the variables:
  118. public IEnumerable<KeyValuePair<string, GlobalVariable>>/*!*/ GlobalVariables {
  119. get { return _globalVariables; }
  120. }
  121. #endregion
  122. #region Random Number Generator
  123. private readonly object _randomNumberGeneratorLock = new object();
  124. private Random _randomNumberGenerator; // lazy
  125. private object _randomNumberGeneratorSeed = ScriptingRuntimeHelpers.Int32ToObject(0);
  126. public object RandomNumberGeneratorSeed {
  127. get { return _randomNumberGeneratorSeed; }
  128. }
  129. public void SeedRandomNumberGenerator(IntegerValue value) {
  130. lock (_randomNumberGeneratorLock) {
  131. _randomNumberGenerator = new Random(value.IsFixnum ? value.Fixnum : value.Bignum.GetHashCode());
  132. _randomNumberGeneratorSeed = value.ToObject();
  133. }
  134. }
  135. public Random/*!*/ RandomNumberGenerator {
  136. get {
  137. if (_randomNumberGenerator == null) {
  138. lock (_randomNumberGeneratorLock) {
  139. if (_randomNumberGenerator == null) {
  140. _randomNumberGenerator = new Random();
  141. }
  142. }
  143. }
  144. return _randomNumberGenerator;
  145. }
  146. }
  147. #endregion
  148. #region Threading
  149. // Thread#main
  150. private readonly Thread _mainThread;
  151. // Thread#critical=
  152. // We just need a bool. But we store the Thread object for easier debugging if there is a hang
  153. private Thread _criticalThread;
  154. private readonly object _criticalMonitor = new object();
  155. #endregion
  156. #region Tracing
  157. private readonly RubyInputProvider/*!*/ _inputProvider;
  158. private Proc _traceListener;
  159. [ThreadStatic]
  160. private bool _traceListenerSuspended;
  161. private readonly Stopwatch _upTime;
  162. // TODO: thread-safety
  163. internal Action<Expression, MSA.DynamicExpression> CallSiteCreated { get; set; }
  164. #endregion
  165. #region Look-aside tables
  166. /// <summary>
  167. /// Maps CLR types to Ruby classes/modules.
  168. /// Doesn't contain classes defined in Ruby.
  169. /// </summary>
  170. private readonly Dictionary<Type, RubyModule>/*!*/ _moduleCache;
  171. private object ModuleCacheLock { get { return _moduleCache; } }
  172. /// <summary>
  173. /// Maps CLR namespace trackers to Ruby modules.
  174. /// </summary>
  175. private readonly Dictionary<NamespaceTracker, RubyModule>/*!*/ _namespaceCache;
  176. private object NamespaceCacheLock { get { return _namespaceCache; } }
  177. // Maps objects to InstanceData. The keys store weak references to the objects.
  178. // Objects are compared by reference (identity).
  179. // An entry can be removed as soon as the key object becomes unreachable.
  180. private readonly WeakTable<object, RubyInstanceData>/*!*/ _referenceTypeInstanceData;
  181. private object/*!*/ ReferenceTypeInstanceDataLock { get { return _referenceTypeInstanceData; } }
  182. // Maps values to InstanceData. The keys store value representatives.
  183. // All objects that has the same value (value-equality) map to the same InstanceData.
  184. // Entries cannot be ever freed since anytime in future one may create a new object whose value has already been mapped to InstanceData.
  185. private readonly Dictionary<object, RubyInstanceData>/*!*/ _valueTypeInstanceData;
  186. private object/*!*/ ValueTypeInstanceDataLock { get { return _valueTypeInstanceData; } }
  187. // not thread-safe:
  188. private readonly RubyInstanceData/*!*/ _nilInstanceData = new RubyInstanceData(RubyUtils.NilObjectId);
  189. #endregion
  190. #region Class Hierarchy
  191. public IDisposable/*!*/ ClassHierarchyLocker() {
  192. return _classHierarchyLock.CreateLocker();
  193. }
  194. public IDisposable/*!*/ ClassHierarchyUnlocker() {
  195. return _classHierarchyLock.CreateUnlocker();
  196. }
  197. private readonly CheckedMonitor/*!*/ _classHierarchyLock = new CheckedMonitor();
  198. [Emitted]
  199. public int ConstantAccessVersion = 1;
  200. [Conditional("DEBUG")]
  201. internal void RequiresClassHierarchyLock() {
  202. Debug.Assert(_classHierarchyLock.IsLocked, "Code can only be executed while holding class hierarchy lock.");
  203. }
  204. // classes used by runtime (we need to update initialization generator if any of these are added):
  205. private RubyClass/*!*/ _basicObjectClass;
  206. private RubyModule/*!*/ _kernelModule;
  207. private RubyClass/*!*/ _objectClass;
  208. private RubyClass/*!*/ _classClass;
  209. private RubyClass/*!*/ _moduleClass;
  210. private RubyClass/*!*/ _nilClass;
  211. private RubyClass/*!*/ _trueClass;
  212. private RubyClass/*!*/ _falseClass;
  213. private RubyClass/*!*/ _exceptionClass;
  214. private RubyClass _standardErrorClass;
  215. private RubyClass _comObjectClass;
  216. private Action<RubyModule>/*!*/ _mainSingletonTrait;
  217. // internally set by Initializer:
  218. public RubyClass/*!*/ BasicObjectClass { get { return _basicObjectClass; } }
  219. public RubyModule/*!*/ KernelModule { get { return _kernelModule; } }
  220. public RubyClass/*!*/ ObjectClass { get { return _objectClass; } }
  221. public RubyClass/*!*/ ClassClass { get { return _classClass; } set { _classClass = value; } }
  222. public RubyClass/*!*/ ModuleClass { get { return _moduleClass; } set { _moduleClass = value; } }
  223. public RubyClass/*!*/ NilClass { get { return _nilClass; } set { _nilClass = value; } }
  224. public RubyClass/*!*/ TrueClass { get { return _trueClass; } set { _trueClass = value; } }
  225. public RubyClass/*!*/ FalseClass { get { return _falseClass; } set { _falseClass = value; } }
  226. public RubyClass ExceptionClass { get { return _exceptionClass; } set { _exceptionClass = value; } }
  227. public RubyClass StandardErrorClass { get { return _standardErrorClass; } set { _standardErrorClass = value; } }
  228. internal RubyClass ComObjectClass {
  229. get {
  230. #if !SILVERLIGHT // COM
  231. if (_comObjectClass == null) {
  232. GetOrCreateClass(TypeUtils.ComObjectType);
  233. }
  234. #endif
  235. return _comObjectClass;
  236. }
  237. }
  238. // Set of names that method_missing defined on any module was resolved for and that are cached. Lazy init.
  239. //
  240. // Note: We used to have this set per module but that doesn't work - see unit test MethodCallCaching_MethodMissing4.
  241. // Whenever a method is added to a class C we would need to traverse all its subclasses to see if any of them
  242. // has the added method in its MissingMethodsCachedInSites table.
  243. // TODO: Could we optimize this search? If so we could also free the per-module set if mm is removed.
  244. internal HashSet<string> MissingMethodsCachedInSites { get; set; }
  245. #endregion
  246. #region Properties
  247. public PlatformAdaptationLayer/*!*/ Platform {
  248. get { return DomainManager.Platform; }
  249. }
  250. public override LanguageOptions Options {
  251. get { return _options; }
  252. }
  253. public RubyOptions RubyOptions {
  254. get { return _options; }
  255. }
  256. internal RubyScope/*!*/ EmptyScope {
  257. get { return _emptyScope; }
  258. }
  259. public Thread MainThread {
  260. get { return _mainThread; }
  261. }
  262. public MutableString InputSeparator {
  263. get { return _inputSeparator; }
  264. set { _inputSeparator = value; }
  265. }
  266. public MutableString OutputSeparator {
  267. get { return _outputSeparator; }
  268. set { _outputSeparator = value; }
  269. }
  270. public object StringSeparator {
  271. get { return _stringSeparator; }
  272. set { _stringSeparator = value; }
  273. }
  274. public MutableString ItemSeparator {
  275. get { return _itemSeparator; }
  276. set { _itemSeparator = value; }
  277. }
  278. public object CriticalMonitor {
  279. get { return _criticalMonitor; }
  280. }
  281. public Thread CriticalThread {
  282. get { return _criticalThread; }
  283. set { _criticalThread = value; }
  284. }
  285. public Proc TraceListener {
  286. get { return _traceListener; }
  287. set { _traceListener = value; }
  288. }
  289. public RubyInputProvider/*!*/ InputProvider {
  290. get { return _inputProvider; }
  291. }
  292. public object ChildProcessExitStatus {
  293. get { return _childProcessExitStatus; }
  294. set { _childProcessExitStatus = value; }
  295. }
  296. public Scope/*!*/ TopGlobalScope {
  297. get { return _globalScope; }
  298. }
  299. internal RubyMetaBinderFactory/*!*/ MetaBinderFactory {
  300. get { return _metaBinderFactory; }
  301. }
  302. public Loader/*!*/ Loader {
  303. get { return _loader; }
  304. }
  305. public bool ShowCls {
  306. get { return false; }
  307. }
  308. public EqualityComparer/*!*/ EqualityComparer {
  309. get {
  310. if (_equalityComparer == null) {
  311. _equalityComparer = new EqualityComparer(this);
  312. }
  313. return _equalityComparer;
  314. }
  315. }
  316. private EqualityComparer _equalityComparer;
  317. public override Version LanguageVersion {
  318. get { return IronRubyVersion; }
  319. }
  320. public override Guid LanguageGuid {
  321. get { return RubyLanguageGuid; }
  322. }
  323. public override Guid VendorGuid {
  324. get { return LanguageVendor_Microsoft; }
  325. }
  326. public int RuntimeId {
  327. get { return _runtimeId; }
  328. }
  329. internal TopNamespaceTracker/*!*/ Namespaces {
  330. get { return _namespaces; }
  331. }
  332. public object Verbose { get; set; }
  333. private RubyEncoding/*!*/ _defaultExternalEncoding;
  334. public RubyEncoding/*!*/ DefaultExternalEncoding {
  335. get { return _defaultExternalEncoding; }
  336. set {
  337. ContractUtils.RequiresNotNull(value, "value");
  338. _defaultExternalEncoding = value;
  339. }
  340. }
  341. public RubyEncoding DefaultInternalEncoding { get; set; }
  342. #endregion
  343. #region Initialization
  344. public RubyContext(ScriptDomainManager/*!*/ manager, IDictionary<string, object> options)
  345. : base(manager) {
  346. ContractUtils.RequiresNotNull(manager, "manager");
  347. _options = new RubyOptions(options);
  348. _runtimeId = Interlocked.Increment(ref _RuntimeIdGenerator);
  349. _upTime = new Stopwatch();
  350. _upTime.Start();
  351. _binder = new RubyBinder(this);
  352. _symbols = new Dictionary<MutableString, RubySymbol>();
  353. _metaBinderFactory = new RubyMetaBinderFactory(this);
  354. _runtimeErrorSink = new RuntimeErrorSink(this);
  355. _equalityComparer = new EqualityComparer(this);
  356. _globalVariables = new Dictionary<string, GlobalVariable>();
  357. _moduleCache = new Dictionary<Type, RubyModule>();
  358. _namespaceCache = new Dictionary<NamespaceTracker, RubyModule>();
  359. _referenceTypeInstanceData = new WeakTable<object, RubyInstanceData>();
  360. _valueTypeInstanceData = new Dictionary<object, RubyInstanceData>();
  361. _inputProvider = new RubyInputProvider(this, _options.Arguments, _options.LocaleEncoding);
  362. _defaultExternalEncoding = _options.DefaultEncoding ?? _options.LocaleEncoding;
  363. _globalScope = DomainManager.Globals;
  364. _loader = new Loader(this);
  365. _emptyScope = new RubyTopLevelScope(this);
  366. _currentException = null;
  367. _currentSafeLevel = 0;
  368. _childProcessExitStatus = null;
  369. _inputSeparator = MutableString.CreateAscii("\n");
  370. _outputSeparator = null;
  371. _stringSeparator = null;
  372. _itemSeparator = null;
  373. _mainThread = Thread.CurrentThread;
  374. if (_options.MainFile != null) {
  375. CommandLineProgramPath = EncodePath(_options.MainFile);
  376. }
  377. if (_options.Verbosity <= 0) {
  378. Verbose = null;
  379. } else if (_options.Verbosity == 1) {
  380. Verbose = ScriptingRuntimeHelpers.False;
  381. } else {
  382. Verbose = ScriptingRuntimeHelpers.True;
  383. }
  384. _namespaces = new TopNamespaceTracker(manager);
  385. manager.AssemblyLoaded += new EventHandler<AssemblyLoadedEventArgs>((_, e) => AssemblyLoaded(e.Assembly));
  386. foreach (Assembly asm in manager.GetLoadedAssemblyList()) {
  387. AssemblyLoaded(asm);
  388. }
  389. // TODO:
  390. Interlocked.CompareExchange(ref _Default, this, null);
  391. _loader.LoadBuiltins();
  392. Debug.Assert(_exceptionClass != null && _standardErrorClass != null && _nilClass != null);
  393. Debug.Assert(_classClass != null && _moduleClass != null);
  394. // needs to run before globals and constants are initialized:
  395. InitializeFileDescriptors(DomainManager.SharedIO);
  396. InitializeGlobalConstants();
  397. InitializeGlobalVariables();
  398. }
  399. internal RubyBinder/*!*/ Binder {
  400. get { return _binder; }
  401. }
  402. /// <summary>
  403. /// Clears thread static variables.
  404. /// </summary>
  405. internal static void ClearThreadStatics() {
  406. _currentException = null;
  407. }
  408. private void InitializeGlobalVariables() {
  409. // special variables:
  410. Runtime.GlobalVariables.DefineVariablesNoLock(this);
  411. // TODO:
  412. // $-a
  413. // $F
  414. // $-i
  415. // $-l
  416. // $-p
  417. // $?
  418. // $0
  419. DefineGlobalVariableNoLock("PROGRAM_NAME", Runtime.GlobalVariables.CommandLineProgramPath);
  420. DefineGlobalVariableNoLock("stdin", Runtime.GlobalVariables.InputStream);
  421. DefineGlobalVariableNoLock("stdout", Runtime.GlobalVariables.OutputStream);
  422. DefineGlobalVariableNoLock("defout", Runtime.GlobalVariables.OutputStream);
  423. DefineGlobalVariableNoLock("stderr", Runtime.GlobalVariables.ErrorOutputStream);
  424. DefineGlobalVariableNoLock("LOADED_FEATURES", Runtime.GlobalVariables.LoadedFiles);
  425. DefineGlobalVariableNoLock("LOAD_PATH", Runtime.GlobalVariables.LoadPath);
  426. DefineGlobalVariableNoLock("-I", Runtime.GlobalVariables.LoadPath);
  427. DefineGlobalVariableNoLock("-O", Runtime.GlobalVariables.InputSeparator);
  428. DefineGlobalVariableNoLock("-F", Runtime.GlobalVariables.StringSeparator);
  429. DefineGlobalVariableNoLock("FILENAME", Runtime.GlobalVariables.InputFileName);
  430. GlobalVariableInfo debug = new GlobalVariableInfo(DomainManager.Configuration.DebugMode || RubyOptions.DebugVariable);
  431. DefineGlobalVariableNoLock("VERBOSE", Runtime.GlobalVariables.Verbose);
  432. DefineGlobalVariableNoLock("-v", Runtime.GlobalVariables.Verbose);
  433. DefineGlobalVariableNoLock("-w", Runtime.GlobalVariables.Verbose);
  434. DefineGlobalVariableNoLock("DEBUG", debug);
  435. DefineGlobalVariableNoLock("-d", debug);
  436. DefineGlobalVariableNoLock("KCODE", Runtime.GlobalVariables.KCode);
  437. DefineGlobalVariableNoLock("-K", Runtime.GlobalVariables.KCode);
  438. #if !SILVERLIGHT
  439. DefineGlobalVariableNoLock("SAFE", Runtime.GlobalVariables.SafeLevel);
  440. try {
  441. TrySetCurrentProcessVariables();
  442. } catch (SecurityException) {
  443. // nop
  444. }
  445. #endif
  446. }
  447. #if !SILVERLIGHT // process
  448. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
  449. private void TrySetCurrentProcessVariables() {
  450. Process process = Process.GetCurrentProcess();
  451. DefineGlobalVariableNoLock(Symbols.CurrentProcessId, new ReadOnlyGlobalVariableInfo(process.Id));
  452. }
  453. #endif
  454. private void InitializeGlobalConstants() {
  455. Debug.Assert(_objectClass != null);
  456. MutableString version = MutableString.CreateAscii(MriVersion);
  457. MutableString platform = MakePlatformString();
  458. MutableString releaseDate = MutableString.CreateAscii(MriReleaseDate);
  459. MutableString rubyEngine = MutableString.CreateAscii("ironruby");
  460. using (ClassHierarchyLocker()) {
  461. RubyClass obj = _objectClass;
  462. obj.SetConstantNoMutateNoLock("RUBY_ENGINE", rubyEngine);
  463. obj.SetConstantNoMutateNoLock("RUBY_VERSION", version);
  464. obj.SetConstantNoMutateNoLock("RUBY_PATCHLEVEL", MriPatchLevel);
  465. obj.SetConstantNoMutateNoLock("RUBY_PLATFORM", platform);
  466. obj.SetConstantNoMutateNoLock("RUBY_RELEASE_DATE", releaseDate);
  467. obj.SetConstantNoMutateNoLock("RUBY_DESCRIPTION", MutableString.CreateAscii(MakeDescriptionString()));
  468. obj.SetConstantNoMutateNoLock("VERSION", version);
  469. obj.SetConstantNoMutateNoLock("PLATFORM", platform);
  470. obj.SetConstantNoMutateNoLock("RELEASE_DATE", releaseDate);
  471. obj.SetConstantNoMutateNoLock("IRONRUBY_VERSION", MutableString.CreateAscii(RubyContext.IronRubyVersionString));
  472. obj.SetConstantNoMutateNoLock("STDIN", StandardInput);
  473. obj.SetConstantNoMutateNoLock("STDOUT", StandardOutput);
  474. obj.SetConstantNoMutateNoLock("STDERR", StandardErrorOutput);
  475. ConstantStorage argf;
  476. if (obj.TryGetConstantNoAutoloadCheck("ARGF", out argf)) {
  477. _inputProvider.Singleton = argf.Value;
  478. }
  479. obj.SetConstantNoMutateNoLock("ARGV", _inputProvider.CommandLineArguments);
  480. // Hash
  481. // SCRIPT_LINES__
  482. }
  483. }
  484. public static string/*!*/ MakeDescriptionString() {
  485. return String.Format(CultureInfo.InvariantCulture, "IronRuby {0} on {1}", IronRubyVersion, MakeRuntimeDesriptionString());
  486. }
  487. internal static string MakeRuntimeDesriptionString() {
  488. Type mono = typeof(object).Assembly.GetType("Mono.Runtime");
  489. return mono != null ?
  490. (string)mono.GetMethod("GetDisplayName", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, null)
  491. : String.Format(CultureInfo.InvariantCulture, ".NET {0}", Environment.Version);
  492. }
  493. private static MutableString/*!*/ MakePlatformString() {
  494. switch (Environment.OSVersion.Platform) {
  495. case PlatformID.MacOSX:
  496. return MutableString.CreateAscii("i386-darwin");
  497. case PlatformID.Unix:
  498. return MutableString.CreateAscii("i386-linux");
  499. case PlatformID.Win32NT:
  500. case PlatformID.Win32S:
  501. case PlatformID.Win32Windows:
  502. return MutableString.CreateAscii("i386-mswin32");
  503. default:
  504. return MutableString.CreateAscii("unknown");
  505. }
  506. }
  507. private void InitializeFileDescriptors(SharedIO/*!*/ io) {
  508. Debug.Assert(_fileDescriptors.Count == 0);
  509. Stream stream = new ConsoleStream(io, ConsoleStreamType.Input);
  510. StandardInput = new RubyIO(this, stream, AllocateFileDescriptor(stream), IOMode.ReadOnly);
  511. stream = new ConsoleStream(io, ConsoleStreamType.Output);
  512. StandardOutput = new RubyIO(this, stream, AllocateFileDescriptor(stream), IOMode.WriteOnly | IOMode.WriteAppends);
  513. stream = new ConsoleStream(io, ConsoleStreamType.ErrorOutput);
  514. StandardErrorOutput = new RubyIO(this, stream, AllocateFileDescriptor(stream), IOMode.WriteOnly | IOMode.WriteAppends);
  515. }
  516. // TODO: internal
  517. public void RegisterPrimitives(
  518. Action<RubyModule>/*!*/ mainSingletonTrait,
  519. Action<RubyModule>/*!*/ basicObjectInstanceTrait,
  520. Action<RubyModule>/*!*/ basicObjectClassTrait,
  521. Action<RubyModule> basicObjectConstantsInitializer,
  522. Action<RubyModule>/*!*/ kernelInstanceTrait,
  523. Action<RubyModule>/*!*/ kernelClassTrait,
  524. Action<RubyModule> kernelConstantsInitializer,
  525. Action<RubyModule>/*!*/ objectInstanceTrait,
  526. Action<RubyModule>/*!*/ objectClassTrait,
  527. Action<RubyModule> objectConstantsInitializer,
  528. Action<RubyModule>/*!*/ moduleInstanceTrait,
  529. Action<RubyModule>/*!*/ moduleClassTrait,
  530. Action<RubyModule> moduleConstantsInitializer,
  531. Action<RubyModule>/*!*/ classInstanceTrait,
  532. Action<RubyModule>/*!*/ classClassTrait,
  533. Action<RubyModule> classConstantsInitializer) {
  534. Assert.NotNull(mainSingletonTrait, basicObjectInstanceTrait, basicObjectClassTrait);
  535. Assert.NotNull(objectInstanceTrait, kernelInstanceTrait, moduleInstanceTrait, classInstanceTrait);
  536. Assert.NotNull(objectClassTrait, kernelClassTrait, moduleClassTrait, classClassTrait);
  537. _mainSingletonTrait = mainSingletonTrait;
  538. // inheritance hierarchy:
  539. //
  540. // Class
  541. // ^
  542. // BasicObject -> BasicObject'
  543. // ^ ^
  544. // Object -> Object'
  545. // ^ ^
  546. // Module -> Module'
  547. // ^ ^
  548. // Class -> Class'
  549. // ^
  550. // Object'
  551. //
  552. // only Object should expose CLR methods:
  553. TypeTracker objectTracker = ReflectionCache.GetTypeTracker(typeof(object));
  554. var moduleFactories = new Delegate[] {
  555. new Func<RubyScope, BlockParam, RubyClass, object>(RubyModule.CreateAnonymousModule),
  556. };
  557. var classFactories = new Delegate[] {
  558. new Func<RubyScope, BlockParam, RubyClass, RubyClass, object>(RubyClass.CreateAnonymousClass),
  559. };
  560. // locks to comply with lock requirements:
  561. using (ClassHierarchyLocker()) {
  562. _basicObjectClass = new RubyClass(this, Symbols.BasicObject, null, null, basicObjectInstanceTrait, basicObjectConstantsInitializer, null, null, null, null, null, false, false, ModuleRestrictions.Builtin & ~ModuleRestrictions.NoOverrides);
  563. _kernelModule = new RubyModule(this, Symbols.Kernel, kernelInstanceTrait, kernelConstantsInitializer, null, null, null, ModuleRestrictions.Builtin);
  564. _objectClass = new RubyClass(this, Symbols.Object, objectTracker.Type, null, objectInstanceTrait, objectConstantsInitializer, null, _basicObjectClass, new[] { _kernelModule }, objectTracker, null, false, false, ModuleRestrictions.Builtin & ~ModuleRestrictions.NoOverrides);
  565. _moduleClass = new RubyClass(this, Symbols.Module, typeof(RubyModule), null, moduleInstanceTrait, moduleConstantsInitializer, moduleFactories, _objectClass, null, null, null, false, false, ModuleRestrictions.Builtin);
  566. _classClass = new RubyClass(this, Symbols.Class, typeof(RubyClass), null, classInstanceTrait, classConstantsInitializer, classFactories, _moduleClass, null, null, null, false, false, ModuleRestrictions.Builtin);
  567. _basicObjectClass.InitializeImmediateClass(_basicObjectClass.CreateSingletonClass(_classClass, basicObjectClassTrait));
  568. _objectClass.InitializeImmediateClass(_objectClass.CreateSingletonClass(_basicObjectClass.ImmediateClass, objectClassTrait));
  569. _moduleClass.InitializeImmediateClass(_moduleClass.CreateSingletonClass(_objectClass.ImmediateClass, moduleClassTrait));
  570. _classClass.InitializeImmediateClass(_classClass.CreateSingletonClass(_moduleClass.ImmediateClass, classClassTrait));
  571. _moduleClass.InitializeDummySingleton();
  572. _classClass.InitializeDummySingleton();
  573. _basicObjectClass.ImmediateClass.InitializeImmediateClass(_classClass.GetDummySingletonClass());
  574. _objectClass.ImmediateClass.InitializeImmediateClass(_classClass.GetDummySingletonClass());
  575. _moduleClass.ImmediateClass.InitializeImmediateClass(_classClass.GetDummySingletonClass());
  576. _classClass.ImmediateClass.InitializeImmediateClass(_classClass.GetDummySingletonClass());
  577. _kernelModule.InitializeImmediateClass(_moduleClass, kernelClassTrait);
  578. _objectClass.SetConstantNoMutateNoLock(_basicObjectClass.Name, _basicObjectClass);
  579. _objectClass.SetConstantNoMutateNoLock(_moduleClass.Name, _moduleClass);
  580. _objectClass.SetConstantNoMutateNoLock(_classClass.Name, _classClass);
  581. _objectClass.SetConstantNoMutateNoLock(_objectClass.Name, _objectClass);
  582. _objectClass.SetConstantNoMutateNoLock(_kernelModule.Name, _kernelModule);
  583. }
  584. AddModuleToCacheNoLock(typeof(BasicObject), _basicObjectClass);
  585. AddModuleToCacheNoLock(typeof(Kernel), _kernelModule);
  586. AddModuleToCacheNoLock(objectTracker.Type, _objectClass);
  587. AddModuleToCacheNoLock(typeof(RubyObject), _objectClass);
  588. AddModuleToCacheNoLock(_moduleClass.GetUnderlyingSystemType(), _moduleClass);
  589. AddModuleToCacheNoLock(_classClass.GetUnderlyingSystemType(), _classClass);
  590. }
  591. #endregion
  592. #region CLR Types and Namespaces
  593. private void AssemblyLoaded(Assembly/*!*/ assembly) {
  594. _namespaces.LoadAssembly(assembly);
  595. AddExtensionAssembly(assembly);
  596. }
  597. internal void AddModuleToCacheNoLock(Type/*!*/ type, RubyModule/*!*/ module) {
  598. Assert.NotNull(type, module);
  599. _moduleCache.Add(type, module);
  600. }
  601. internal void AddNamespaceToCacheNoLock(NamespaceTracker/*!*/ namespaceTracker, RubyModule/*!*/ module) {
  602. Assert.NotNull(namespaceTracker, module);
  603. _namespaceCache.Add(namespaceTracker, module);
  604. }
  605. internal RubyModule/*!*/ GetOrCreateModule(NamespaceTracker/*!*/ tracker) {
  606. Assert.NotNull(tracker);
  607. lock (ModuleCacheLock) {
  608. return GetOrCreateModuleNoLock(tracker);
  609. }
  610. }
  611. internal bool TryGetModule(NamespaceTracker/*!*/ namespaceTracker, out RubyModule result) {
  612. lock (NamespaceCacheLock) {
  613. return _namespaceCache.TryGetValue(namespaceTracker, out result);
  614. }
  615. }
  616. internal RubyModule/*!*/ GetOrCreateModule(Type/*!*/ moduleType) {
  617. Debug.Assert(RubyModule.IsModuleType(moduleType));
  618. lock (ModuleCacheLock) {
  619. return GetOrCreateModuleNoLock(moduleType);
  620. }
  621. }
  622. public bool TryGetModule(Type/*!*/ type, out RubyModule result) {
  623. lock (ModuleCacheLock) {
  624. return _moduleCache.TryGetValue(type, out result);
  625. }
  626. }
  627. internal bool TryGetModuleNoLock(Type/*!*/ type, out RubyModule result) {
  628. return _moduleCache.TryGetValue(type, out result);
  629. }
  630. internal bool TryGetClassNoLock(Type/*!*/ type, out RubyClass result) {
  631. RubyModule module;
  632. if (_moduleCache.TryGetValue(type, out module)) {
  633. result = module as RubyClass;
  634. if (result == null) {
  635. throw new InvalidOperationException("Specified type doesn't represent a class");
  636. }
  637. return true;
  638. } else {
  639. result = null;
  640. return false;
  641. }
  642. }
  643. internal RubyClass/*!*/ GetOrCreateClass(Type/*!*/ type) {
  644. lock (ModuleCacheLock) {
  645. return GetOrCreateClassNoLock(type);
  646. }
  647. }
  648. private RubyModule/*!*/ GetOrCreateModuleNoLock(NamespaceTracker/*!*/ tracker) {
  649. Assert.NotNull(tracker);
  650. RubyModule result;
  651. if (_namespaceCache.TryGetValue(tracker, out result)) {
  652. return result;
  653. }
  654. result = CreateModule(GetQualifiedName(tracker), null, null, null, null, tracker, null, ModuleRestrictions.None);
  655. _namespaceCache[tracker] = result;
  656. return result;
  657. }
  658. private RubyModule/*!*/ GetOrCreateModuleNoLock(Type/*!*/ moduleType) {
  659. Debug.Assert(RubyModule.IsModuleType(moduleType));
  660. RubyModule result;
  661. if (_moduleCache.TryGetValue(moduleType, out result)) {
  662. return result;
  663. }
  664. TypeTracker tracker = (TypeTracker)TypeTracker.FromMemberInfo(moduleType);
  665. RubyModule[] mixins;
  666. if (moduleType.IsGenericType && !moduleType.IsGenericTypeDefinition) {
  667. // I<T0..Tn> mixes in its generic definition I<,..,>
  668. mixins = new[] { GetOrCreateModuleNoLock(moduleType.GetGenericTypeDefinition()) };
  669. } else {
  670. mixins = null;
  671. }
  672. result = CreateModule(GetQualifiedNameNoLock(moduleType), null, null, null, mixins, null, tracker, ModuleRestrictions.None);
  673. _moduleCache[moduleType] = result;
  674. return result;
  675. }
  676. private RubyClass/*!*/ GetOrCreateClassNoLock(Type/*!*/ type) {
  677. Debug.Assert(!RubyModule.IsModuleType(type));
  678. RubyClass result;
  679. if (TryGetClassNoLock(type, out result)) {
  680. return result;
  681. }
  682. RubyClass baseClass;
  683. if (type.IsByRef) {
  684. baseClass = _objectClass;
  685. } else {
  686. baseClass = GetOrCreateClassNoLock(type.BaseType);
  687. }
  688. TypeTracker tracker = (TypeTracker)TypeTracker.FromMemberInfo(type);
  689. RubyModule[] clrMixins = GetClrMixinsNoLock(type);
  690. RubyModule[] expandedMixins;
  691. if (clrMixins != null) {
  692. using (ClassHierarchyLocker()) {
  693. expandedMixins = RubyModule.ExpandMixinsNoLock(baseClass, clrMixins);
  694. }
  695. } else {
  696. expandedMixins = RubyModule.EmptyArray;
  697. }
  698. result = CreateClass(
  699. GetQualifiedNameNoLock(type), type, null, null, null, null, null,
  700. baseClass, expandedMixins, tracker, null, false, false, ModuleRestrictions.None
  701. );
  702. if (TypeUtils.IsComObjectType(type)) {
  703. _comObjectClass = result;
  704. }
  705. _moduleCache[type] = result;
  706. return result;
  707. }
  708. /// <summary>
  709. /// An interface is mixed into the type that implements it.
  710. /// A generic type definition is mixed into its instantiations.
  711. ///
  712. /// In both cases these modules don't themselves contribute any callable CLR methods
  713. /// yet they might contribute CLR extension methods and Ruby methods defined on them.
  714. /// </summary>
  715. private RubyModule[] GetClrMixinsNoLock(Type/*!*/ type) {
  716. List<RubyModule> modules = new List<RubyModule>();
  717. if (type.IsGenericType && !type.IsGenericTypeDefinition) {
  718. modules.Add(GetOrCreateModuleNoLock(type.GetGenericTypeDefinition()));
  719. }
  720. if (type.IsArray) {
  721. if (type.GetArrayRank() > 1) {
  722. RubyModule module;
  723. if (TryGetModuleNoLock(typeof(MultiDimensionalArray), out module)) {
  724. modules.Add(module);
  725. }
  726. }
  727. } else if (type.IsEnum) {
  728. if (type.IsDefined(typeof(FlagsAttribute), false)) {
  729. RubyModule module;
  730. if (TryGetModuleNoLock(typeof(FlagEnumeration), out module)) {
  731. modules.Add(module);
  732. }
  733. }
  734. }
  735. foreach (Type iface in ReflectionUtils.GetDeclaredInterfaces(type)) {
  736. modules.Add(GetOrCreateModuleNoLock(iface));
  737. }
  738. return modules.Count > 0 ? modules.ToArray() : null;
  739. }
  740. #endregion
  741. #region CLR Extension Methods
  742. private readonly object ExtensionsLock = new object();
  743. // List of assemblies that might include extension methods but whose processing was delayed until the first call of use_clr_extensions.
  744. // Null once use_clr_extensions has been called.
  745. private List<Assembly> _potentialExtensionAssemblies = new List<Assembly>();
  746. // A list of extension methods that are available for activation. Grouped by a declaring namespace.
  747. // Value is null if the namepsace has been activated.
  748. private Dictionary<string, List<IEnumerable<ExtensionMethodInfo>>> _availableExtensions;
  749. private void AddExtensionAssembly(Assembly/*!*/ assembly) {
  750. if (_potentialExtensionAssemblies != null) {
  751. lock (ExtensionsLock) {
  752. if (_potentialExtensionAssemblies != null) {
  753. _potentialExtensionAssemblies.Add(assembly);
  754. return;
  755. }
  756. }
  757. }
  758. LoadExtensions(ReflectionUtils.GetVisibleExtensionMethodGroups(assembly, true));
  759. }
  760. private void LoadExtensions(IEnumerable<KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>>/*!*/ extensionMethodGroups) {
  761. List<IEnumerable<ExtensionMethodInfo>> immediatelyActivated = null;
  762. lock (ExtensionsLock) {
  763. foreach (var extensionMethodGroup in extensionMethodGroups) {
  764. if (_availableExtensions == null) {
  765. _availableExtensions = new Dictionary<string, List<IEnumerable<ExtensionMethodInfo>>>();
  766. }
  767. string ns = extensionMethodGroup.Key;
  768. List<IEnumerable<ExtensionMethodInfo>> extensions;
  769. if (_availableExtensions.TryGetValue(ns, out extensions)) {
  770. if (extensions == null) {
  771. if (immediatelyActivated == null) {
  772. immediatelyActivated = new List<IEnumerable<ExtensionMethodInfo>>();
  773. }
  774. extensions = immediatelyActivated;
  775. }
  776. } else {
  777. _availableExtensions.Add(ns, extensions = new List<IEnumerable<ExtensionMethodInfo>>());
  778. }
  779. extensions.Add(extensionMethodGroup.Value);
  780. }
  781. }
  782. if (immediatelyActivated != null) {
  783. ActivateExtensions(immediatelyActivated);
  784. }
  785. }
  786. public void ActivateExtensions(string/*!*/ @namespace) {
  787. ContractUtils.RequiresNotNull(@namespace, "namespace");
  788. Assembly[] assemblies = null;
  789. if (_potentialExtensionAssemblies != null) {
  790. lock (ExtensionsLock) {
  791. if (_potentialExtensionAssemblies != null) {
  792. assemblies = _potentialExtensionAssemblies.ToArray();
  793. _potentialExtensionAssemblies = null;
  794. }
  795. }
  796. }
  797. if (assemblies != null) {
  798. var extensionGroups = new List<KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>>();
  799. foreach (var assembly in assemblies) {
  800. extensionGroups.AddRange(ReflectionUtils.GetVisibleExtensionMethodGroups(assembly, true));
  801. }
  802. LoadExtensions(extensionGroups);
  803. }
  804. List<IEnumerable<ExtensionMethodInfo>> extensions;
  805. lock (ExtensionsLock) {
  806. _availableExtensions.TryGetValue(@namespace, out extensions);
  807. // activate namespace:
  808. _availableExtensions[@namespace] = null;
  809. }
  810. if (extensions != null) {
  811. ActivateExtensions(extensions);
  812. }
  813. }
  814. private void ActivateExtensions(List<IEnumerable<ExtensionMethodInfo>>/*!*/ extensionLists) {
  815. var groupedByType = new Dictionary<Type, List<ExtensionMethodInfo>>();
  816. foreach (var extensionList in extensionLists) {
  817. foreach (var extension in extensionList) {
  818. Type extendedType = extension.ExtendedType;
  819. Debug.Assert(!extendedType.IsGenericTypeDefinition && !extendedType.IsPointer && !extendedType.IsByRef);
  820. Type target;
  821. if (extendedType.ContainsGenericParameters) {
  822. if (extendedType.IsGenericParameter) {
  823. // TODO: we can do better if there are constraints defined on the parameter
  824. target = typeof(object);
  825. } else {
  826. target = extendedType.IsArray ? typeof(Array) : extendedType.GetGenericTypeDefinition();
  827. }
  828. } else {
  829. target = extendedType;
  830. }
  831. List<ExtensionMethodInfo> list;
  832. if (!groupedByType.TryGetValue(target, out list)) {
  833. groupedByType.Add(target, list = new List<ExtensionMethodInfo>());
  834. }
  835. list.Add(extension);
  836. }
  837. }
  838. using (ClassHierarchyLocker()) {
  839. lock (ModuleCacheLock) {
  840. foreach (var entry in groupedByType) {
  841. Type target = entry.Key;
  842. var methods = entry.Value;
  843. RubyModule targetModule = (target.IsGenericTypeDefinition || target.IsInterface) ? GetOrCreateModuleNoLock(target) : GetOrCreateClassNoLock(target);
  844. targetModule.AddExtensionMethodsNoLock(methods);
  845. }
  846. }
  847. }
  848. }
  849. #endregion
  850. #region Class and Module Factories (thread-safe)
  851. /// <summary>
  852. /// Class factory. Do not use RubyClass constructor except for special cases (Object, Class, Module, singleton classes).
  853. /// </summary>
  854. internal RubyClass/*!*/ CreateClass(string name, Type type, object classSingletonOf,
  855. Action<RubyModule> instanceTrait, Action<RubyModule> classTrait, Action<RubyModule> constantsInitializer, Delegate/*!*/[] factories,
  856. RubyClass/*!*/ superClass, RubyModule/*!*/[] expandedMixins, TypeTracker tracker, RubyStruct.Info structInfo,
  857. bool isRubyClass, bool isSingletonClass, ModuleRestrictions restrictions) {
  858. Assert.NotNull(superClass);
  859. RubyClass result = new RubyClass(this, name, type, classSingletonOf,
  860. instanceTrait, constantsInitializer, factories, superClass, expandedMixins, tracker, structInfo,
  861. isRubyClass, isSingletonClass, restrictions
  862. );
  863. result.InitializeImmediateClass(superClass.ImmediateClass, classTrait);
  864. return result;
  865. }
  866. /// <summary>
  867. /// Module factory. Do not use RubyModule constructor except special cases (Kernel).
  868. /// </summary>
  869. internal RubyModule/*!*/ CreateModule(string name,
  870. Action<RubyModule> instanceTrait, Action<RubyModule> classTrait, Action<RubyModule> constantsInitializer,
  871. RubyModule/*!*/[] expandedMixins, NamespaceTracker namespaceTracker, TypeTracker typeTracker, ModuleRestrictions restrictions) {
  872. RubyModule result = new RubyModule(
  873. this, name, instanceTrait, constantsInitializer, expandedMixins, namespaceTracker, typeTracker, restrictions
  874. );
  875. result.InitializeImmediateClass(_moduleClass, classTrait);
  876. return result;
  877. }
  878. /// <summary>
  879. /// Creates a singleton class for specified object unless it already exists.
  880. /// </summary>
  881. public RubyClass/*!*/ GetOrCreateSingletonClass(object obj) {
  882. RubyModule module = obj as RubyModule;
  883. if (module != null) {
  884. return module.GetOrCreateSingletonClass();
  885. }
  886. return GetOrCreateInstanceSingleton(obj, null, null, null, null);
  887. }
  888. internal RubyClass/*!*/ GetOrCreateMainSingleton(object obj, RubyModule/*!*/[] expandedMixins) {
  889. return GetOrCreateInstanceSingleton(obj, _mainSingletonTrait, null, null, expandedMixins);
  890. }
  891. internal RubyClass/*!*/ GetOrCreateInstanceSingleton(object obj, Action<RubyModule> instanceTrait, Action<RubyModule> classTrait,
  892. Action<RubyModule> constantsInitializer, RubyModule/*!*/[] expandedMixins) {
  893. Debug.Assert(!(obj is RubyModule));
  894. Debug.Assert(RubyUtils.HasSingletonClass(obj));
  895. if (obj == null) {
  896. return _nilClass;
  897. }
  898. if (obj is bool) {
  899. return (bool)obj ? _trueClass : _falseClass;
  900. }
  901. RubyInstanceData data = null;
  902. RubyClass immediate = GetImmediateClassOf(obj, ref data);
  903. if (immediate.IsSingletonClass) {
  904. Debug.Assert(!immediate.IsDummySingletonClass);
  905. return immediate;
  906. }
  907. RubyClass result = CreateClass(
  908. null, null, obj, instanceTrait, classTrait, constantsInitializer, null,
  909. immediate, expandedMixins, null, null, true, true, ModuleRestrictions.None
  910. );
  911. using (ClassHierarchyLocker()) {
  912. // singleton might have been created by another thread:
  913. immediate = GetImmediateClassOf(obj, ref data);
  914. if (immediate.IsSingletonClass) {
  915. Debug.Assert(!immediate.IsDummySingletonClass);
  916. return immediate;
  917. }
  918. SetInstanceSingletonOfNoLock(obj, ref data, result);
  919. if (!(obj is IRubyObject)) {
  920. PerfTrack.NoteEvent(PerfTrack.Categories.Count, "Non-IRO singleton created " + immediate.NominalClass.Name);
  921. }
  922. }
  923. Debug.Assert(result.IsSingletonClass && !result.IsDummySingletonClass);
  924. return result;
  925. }
  926. /// <summary>
  927. /// Defines a new module nested in the given owner.
  928. /// The module is published into the global scope if the owner is Object.
  929. ///
  930. /// Thread safe.
  931. /// </summary>
  932. internal RubyModule/*!*/ DefineModule(RubyModule/*!*/ owner, string/*!*/ name) {
  933. RubyModule result = CreateModule(owner.MakeNestedModuleName(name), null, null, null, null, null, null, ModuleRestrictions.None);
  934. PublishModule(name, owner, result);
  935. return result;
  936. }
  937. /// <summary>
  938. /// Defines a new class nested in the given owner.
  939. /// The module is published into the global scope it if is not anonymous and the owner is Object.
  940. ///
  941. /// Thread safe.
  942. /// Triggers "inherited" event.
  943. /// </summary>
  944. internal RubyClass/*!*/ DefineClass(RubyModule/*!*/ owner, string name, RubyClass/*!*/ superClass, RubyStruct.Info structInfo) {
  945. Assert.NotNull(owner, superClass);
  946. if (superClass.TypeTracker != null && superClass.TypeTracker.Type.ContainsGenericParameters) {
  947. throw RubyExceptions.CreateTypeError(String.Format(
  948. "{0}: cannot inherit from open generic instantiation {1}. Only closed instantiations are supported.",
  949. name, superClass.Name
  950. ));
  951. }
  952. string qualifiedName = owner.MakeNestedModuleName(name);
  953. RubyClass result = CreateClass(
  954. qualifiedName, null, null, null, null, null, null, superClass, null, null, structInfo, true, false, ModuleRestrictions.None
  955. );
  956. PublishModule(name, owner, result);
  957. superClass.ClassInheritedEvent(result);
  958. return result;
  959. }
  960. private static void PublishModule(string name, RubyModule/*!*/ owner, RubyModule/*!*/ module) {
  961. if (name != null) {
  962. owner.SetConstant(name, module);
  963. if (owner.IsObjectClass) {
  964. module.Publish(name);
  965. }
  966. }
  967. }
  968. #endregion
  969. #region Libraries (thread-safe)
  970. //
  971. // Scenario…

Large files files are truncated, but you can click here to view the full file