Example #1
0
        private ConstantLookupResult TryLookupConstantNoLock(bool included, bool inherited, RubyGlobalScope autoloadScope,
            string/*!*/ name, out ConstantStorage value) {

            Context.RequiresClassHierarchyLock();
            Debug.Assert(included || !inherited);

            value = default(ConstantStorage);
            while (true) {
                ConstantStorage result;

                RubyModule owner = included ? 
                    TryResolveConstantNoAutoloadCheck(inherited, name, out result) :
                    (TryGetConstantNoAutoloadCheck(name, out result) ? this : null);

                if (owner == null) {
                    return ConstantLookupResult.NotFound;
                }

                var autoloaded = result.Value as AutoloadedConstant;
                if (autoloaded == null) {
                    value = result;
                    return ConstantLookupResult.Found;
                }

                if (autoloadScope == null) {
                    return ConstantLookupResult.FoundAutoload;
                }

                if (autoloadScope.Context != Context) {
                    throw RubyExceptions.CreateTypeError(String.Format("Cannot autoload constants to a foreign runtime #{0}", autoloadScope.Context.RuntimeId));
                }

                // autoloaded constants are removed before the associated file is loaded:
                object _;
                owner.TryRemoveConstantNoLock(name, out _);
                               
                // load file and try lookup again (releases the class hierarchy lock when loading the file):
                if (!autoloaded.Load(autoloadScope)) {
                    return ConstantLookupResult.NotFound;
                }
            }
        }
Example #2
0
        // thread-safe:
        // Returns null on success, the lexically inner-most module on failure.
        internal RubyModule TryResolveConstantNoLock(RubyGlobalScope autoloadScope, string/*!*/ name, out ConstantStorage result) {
            var context = RubyContext;
            context.RequiresClassHierarchyLock();
            
            RubyScope scope = this;

            // lexical lookup first:
            RubyModule innerMostModule = null;
            do {
                RubyModule module = scope.Module;

                if (module != null) {
                    if (module.TryGetConstant(context, autoloadScope, name, out result)) {
                        return null;
                    }

                    // remember the module:
                    if (innerMostModule == null) {
                        innerMostModule = module;
                    }
                }

                scope = scope.Parent;
            } while (scope != null);

            // check the inner most module and it's base classes/mixins:
            if (innerMostModule != null) {
                if (innerMostModule.TryResolveConstant(context, autoloadScope, name, out result)) {
                    return null;
                }
            } else {
                innerMostModule = context.ObjectClass;
            }

            if (context.ObjectClass.TryResolveConstant(context, autoloadScope, name, out result)) {
                return null;
            }

            return innerMostModule;
        }
Example #3
0
 /// <summary>
 /// Get constant defined in this module or any of its ancestors. 
 /// Autoloads if autoloadScope is not null.
 /// </summary>
 /// <remarks>
 /// Thread safe.
 /// </remarks>
 internal bool TryResolveConstant(RubyGlobalScope autoloadScope, string/*!*/ name, out ConstantStorage value) {
     using (Context.ClassHierarchyLocker()) {
         return TryResolveConstantNoLock(autoloadScope, name, out value);
     }
 }        
Example #4
0
 /// <summary>
 /// Get constant defined in this module or any of its ancestors.
 /// </summary>
 internal bool TryResolveConstantNoLock(RubyGlobalScope autoloadScope, string/*!*/ name, out ConstantStorage value) {
     Context.RequiresClassHierarchyLock();
     return TryLookupConstantNoLock(true, true, autoloadScope, name, out value) != ConstantLookupResult.NotFound;
 }
Example #5
0
        internal void SetConstantNoMutateNoLock(string/*!*/ name, object value) {
            Context.RequiresClassHierarchyLock();

            InitializeConstantsNoLock();
            _context.ConstantAccessVersion++;
            _constants[name] = new ConstantStorage(value);
        }
Example #6
0
 internal bool TryResolveConstant(RubyContext/*!*/ callerContext, RubyGlobalScope autoloadScope, string/*!*/ name, out ConstantStorage value) {
     return callerContext != Context ?
         TryResolveConstant(autoloadScope, name, out value) :
         TryResolveConstantNoLock(autoloadScope, name, out value);
 }
Example #7
0
        private void LoadNestedTypes() {
            Context.RequiresClassHierarchyLock();
            Debug.Assert(_constants != null && _constants.Count == 0);

            // TODO: Inherited generic overloads. We need a custom TypeGroup to do it right - part of the type group might be removed

            // TODO: protected types
            var bindingFlags = BindingFlags.Public | BindingFlags.DeclaredOnly;
            if (Context.DomainManager.Configuration.PrivateBinding) {
                bindingFlags |= BindingFlags.NonPublic;
            }

            // if the constant is redefined/removed from the base class. This is similar to method overload inheritance.
            Type[] types = _typeTracker.Type.GetNestedTypes(bindingFlags);
            var trackers = new List<TypeTracker>();
            var names = new List<string>();
            foreach (var type in types) {
                TypeTracker tracker = (NestedTypeTracker)MemberTracker.FromMemberInfo(type);

                if (type.IsGenericType) {
                    var name = ReflectionUtils.GetNormalizedTypeName(type);
                    int index = names.IndexOf(name);
                    if (index != -1) {
                        trackers[index] = TypeGroup.UpdateTypeEntity(trackers[index], tracker);
                        names[index] = name;
                    } else {
                        trackers.Add(tracker);
                        names.Add(name);
                    }
                } else {
                    trackers.Add(tracker);
                    names.Add(type.Name);
                }
            }

            for (int i = 0; i < trackers.Count; i++) {
                var tracker = trackers[i];
                ConstantStorage storage;
                if (tracker is TypeGroup) {
                    storage = new ConstantStorage(tracker, new WeakReference(tracker));
                } else {
                    var module = Context.GetModule(tracker.Type);
                    storage = new ConstantStorage(module, module.WeakSelf);
                }
                _constants[names[i]] = storage;
            }
        }
Example #8
0
        // Returns the owner of the constant (this module) or null if the constant is not found.
        internal bool TryGetConstantNoAutoloadCheck(string/*!*/ name, out ConstantStorage storage) {
            Context.RequiresClassHierarchyLock();

            InitializeConstantsNoLock();

            if (_constants.TryGetValue(name, out storage)) {
                if (storage.IsRemoved) {
                    storage = default(ConstantStorage);
                    return false;
                } else {
                    return true;
                }
            }

            if (_namespaceTracker != null) {
                object value;
                if (_namespaceTracker.TryGetValue(SymbolTable.StringToId(name), out value)) {
                    storage = new ConstantStorage( _context.TrackerToModule(value));
                    return true;
                }
            }

            storage = default(ConstantStorage);
            return false;
        }
Example #9
0
        // Returns the owner of the constant or null if the constant is not found.
        private RubyModule TryResolveConstantNoAutoloadCheck(bool inherited, string/*!*/ name, out ConstantStorage value) {
            Context.RequiresClassHierarchyLock();

            var storage = default(ConstantStorage);
            RubyModule owner = null;
            if (ForEachAncestor(inherited, (module) => (owner = module).TryGetConstantNoAutoloadCheck(name, out storage))) {
                value = storage;
                return owner;
            } else {
                value = storage;
                return null;
            }
        }
Example #10
0
        // thread-safe:
        // Returns null on success, the lexically inner-most module on failure.
        internal RubyModule TryResolveConstantNoLock(RubyGlobalScope autoloadScope, string /*!*/ name, out ConstantStorage result)
        {
            var context = RubyContext;

            context.RequiresClassHierarchyLock();

            RubyScope scope = this;

            // lexical lookup first:
            RubyModule innerMostModule = null;

            do
            {
                RubyModule module = scope.Module;

                if (module != null)
                {
                    if (module.TryGetConstant(context, autoloadScope, name, out result))
                    {
                        return(null);
                    }

                    // remember the module:
                    if (innerMostModule == null)
                    {
                        innerMostModule = module;
                    }
                }

                scope = scope.Parent;
            } while (scope != null);

            // check the inner most module and it's base classes/mixins:
            if (innerMostModule != null)
            {
                if (innerMostModule.TryResolveConstant(context, autoloadScope, name, out result))
                {
                    return(null);
                }
            }
            else
            {
                innerMostModule = context.ObjectClass;
            }

            if (context.ObjectClass.TryResolveConstant(context, autoloadScope, name, out result))
            {
                return(null);
            }

            return(innerMostModule);
        }
Example #11
0
 // Direct lookup into the constant table (if it exists).
 internal bool TryGetConstantNoAutoloadNoInit(string/*!*/ name, out ConstantStorage storage) {
     Context.RequiresClassHierarchyLock();
     storage = default(ConstantStorage);
     return _constants != null && _constants.TryGetValue(name, out storage) && !storage.IsRemoved;
 }