예제 #1
0
        /// <summary>
        /// Recompiles the class which involves recalculating caches state.
        /// </summary>
        /// <remarks>
        /// This flushes internal caches for the class and any affected
        /// classes (subclasses or possible superclasses).
        ///
        /// The process includes:
        /// - Resetting cached subclasses collection.
        /// - Remapping instance-names to indexes.
        /// - Remapping class-instance-names to indexes.
        /// - Register the class for mapping between native .Net types and Smalltalk classes.
        /// - Write-protects dictionaries of imported pools, variables and methods (etc.)
        /// </remarks>
        public void Recompile()
        {
            SmalltalkClass superclass = this.Superclass;

            if (superclass != null)
            {
                lock (superclass)
                    superclass._subclasses = null;
            }

            this.RecompileIndexedVariables();
            this.RegisterNativeTypeMapping();

            lock (this)
                this._subclasses = null;
            foreach (SmalltalkClass cls in this.Subclasses)
            {
                cls.Recompile();
            }

            this.ClassInstanceVariableBindings.WriteProtect();
            this.ClassVariableBindings.WriteProtect();
            this.ImportedPoolBindings.WriteProtect();
            this.InstanceBehavior.WriteProtect();
            this.InstanceVariableBindings.WriteProtect();
        }
예제 #2
0
 /// <summary>
 /// Create a new SmalltalkObject for a given SmalltalkClass.
 /// </summary>
 /// <param name="cls">The SmalltalkClass that this object will be instance of.</param>
 public SmalltalkObject(SmalltalkClass cls)
 {
     if (cls == null)
     {
         throw new ArgumentNullException();
     }
     this.Class             = cls;
     this.InstanceVariables = new object[cls.InstanceSize];
 }
예제 #3
0
 /// <summary>
 /// Create a new ByteIndexable SmalltalkObject for a given SmalltalkClass.
 /// </summary>
 /// <param name="cls">The SmalltalkClass that this object will be instance of.</param>
 /// <param name="objectSize">Number of unnamed instance variables.</param>
 public ByteIndexableSmalltalkObject(SmalltalkClass cls, int objectSize)
     : base(cls)
 {
     if (cls.InstanceState != SmalltalkClass.InstanceStateEnum.ByteIndexable)
     {
         throw new ArgumentOutOfRangeException("cls", cls.InstanceState, "Expected a ByteIndexable class");
     }
     if (objectSize < 0)
     {
         throw new ArgumentOutOfRangeException("objectSize");
     }
     this.Contents = new byte[objectSize];
 }
예제 #4
0
 /// <summary>
 /// Internal! This is used by the Installer to create new classes.
 /// </summary>
 /// <param name="runtime">Smalltalk runtime this class is part of.</param>
 /// <param name="name">Name of the class.</param>
 /// <param name="superclass">Optional binding to the class' superclass.</param>
 /// <param name="instanceState">State of the class' instances (named, object-indexable, byte-indexable).</param>
 /// <param name="instanceVariables">Instance variables bindings. Those are initially not initialized.</param>
 /// <param name="classVariables">Class variable binding.</param>
 /// <param name="classInstanceVariables">Class-instance variables bindings. Those are initially not initialized.</param>
 /// <param name="importedPools">Collection of pools that are imported by the class.</param>
 /// <param name="instanceMethods">Collection with the methods defining the instance behaviors.</param>
 /// <param name="classMethods">Collection with the methods defining the class behaviors.</param>
 public SmalltalkClass(SmalltalkRuntime runtime, Symbol name, ClassBinding superclass, InstanceStateEnum instanceState,
                       BindingDictionary <InstanceVariableBinding> instanceVariables, DiscreteBindingDictionary <ClassVariableBinding> classVariables,
                       BindingDictionary <ClassInstanceVariableBinding> classInstanceVariables, DiscreteBindingDictionary <PoolBinding> importedPools,
                       InstanceMethodDictionary instanceMethods, ClassMethodDictionary classMethods)
 {
     if (runtime == null)
     {
         throw new ArgumentNullException("runtime");
     }
     if ((name == null) || (name.Value.Length == 0))
     {
         throw new ArgumentNullException("name");
     }
     if (!SmalltalkClass.ValidateIdentifiers <InstanceVariableBinding>(instanceVariables))
     {
         throw new ArgumentException("Invalid or duplicate instance variable name found", "instanceVariables");
     }
     if (!SmalltalkClass.ValidateIdentifiers <ClassVariableBinding>(classVariables))
     {
         throw new ArgumentException("Invalid or duplicate class variable name found", "classVariables");
     }
     if (!SmalltalkClass.ValidateIdentifiers <ClassInstanceVariableBinding>(classInstanceVariables))
     {
         throw new ArgumentException("Invalid or duplicate class instance variable name found", "classInstanceVariables");
     }
     if (!SmalltalkClass.ValidateIdentifiers <PoolBinding>(importedPools))
     {
         throw new ArgumentException("Invalid or duplicate imported pool name found", "importedPools");
     }
     if (!SmalltalkClass.CheckDuplicates <InstanceVariableBinding, ClassVariableBinding>(instanceVariables, classVariables))
     {
         throw new ArgumentException("Duplicate instance or class variable name. Instance and class variable names must be unique.");
     }
     if (!SmalltalkClass.CheckDuplicates <ClassInstanceVariableBinding, ClassVariableBinding>(classInstanceVariables, classVariables))
     {
         throw new ArgumentException("Duplicate class-instance or class variable name. Class-instance and class variable names must be unique.");
     }
     this.Runtime = runtime;
     this.ClassInstanceVariableBindings = classInstanceVariables ?? new BindingDictionary <ClassInstanceVariableBinding>(this.Runtime, 1);
     this.ClassBehavior            = classMethods ?? new ClassMethodDictionary(this.Runtime);
     this.ClassVariableBindings    = classVariables ?? new DiscreteBindingDictionary <ClassVariableBinding>(this.Runtime, 1);
     this.ImportedPoolBindings     = importedPools ?? new DiscreteBindingDictionary <PoolBinding>(this.Runtime, 1);
     this.InstanceBehavior         = instanceMethods ?? new InstanceMethodDictionary(this.Runtime);
     this.InstanceState            = instanceState;
     this.InstanceVariableBindings = instanceVariables ?? new BindingDictionary <InstanceVariableBinding>(this.Runtime, 1);
     this.Name = name;
     this.SuperclassBinding      = superclass; // Null is OK .... Object has null
     this.InstanceSize           = 0;
     this.ClassInstanceSize      = 0;
     this.ClassInstanceVariables = new object[0];
 }
예제 #5
0
        private void RecompileIndexedVariables()
        {
            lock (this)
                this._subclasses = null;

#if DEBUG
            {
                // Validate that we don't have some bug or inconsistency in the calculation.
                SmalltalkClass scls    = this.Superclass;
                int            lastVar = Int32.MaxValue;
                while (scls != null)
                {
                    if (scls.InstanceSize > lastVar)
                    {
                        throw new InvalidOperationException("Broken instance variable binding. Bad implementation.");
                    }

                    IEnumerable <InstanceVariableBinding> vars = scls.InstanceVariableBindings;
                    if (vars.Any())
                    {
                        int min = vars.Min(binding => binding.Value);
                        int max = vars.Max(binding => binding.Value);
                        if (max >= lastVar)
                        {
                            throw new InvalidOperationException("Broken instance variable binding. Bad implementation.");
                        }
                        lastVar = min;
                    }
                    else
                    {
                        lastVar = scls.InstanceSize;
                    }
                    scls = scls.Superclass;
                }
                // ... and the class-instance variables ...
                scls    = this.Superclass;
                lastVar = Int32.MaxValue;
                while (scls != null)
                {
                    if (scls.ClassInstanceSize > lastVar)
                    {
                        throw new InvalidOperationException("Broken class-instance variable binding. Bad implementation.");
                    }

                    IEnumerable <ClassInstanceVariableBinding> vars = scls.ClassInstanceVariableBindings;
                    if (vars.Any())
                    {
                        int min = vars.Min(binding => binding.Value);
                        int max = vars.Max(binding => binding.Value);
                        if (max >= lastVar)
                        {
                            throw new InvalidOperationException("Broken class-instance variable binding. Bad implementation.");
                        }
                        lastVar = min;
                    }
                    else
                    {
                        lastVar = scls.ClassInstanceSize;
                    }
                    scls = scls.Superclass;
                }
            }
#endif
            SmalltalkClass cls = this.Superclass;
            int            idx = (cls == null) ? 0 : cls.InstanceSize;
            foreach (InstanceVariableBinding binding in this.InstanceVariableBindings)
            {
                binding.SetValue(idx);
                idx++;
            }
            this.InstanceSize = idx;

            idx = (cls == null) ? 0 : cls.ClassInstanceSize;
            foreach (ClassInstanceVariableBinding binding in this.ClassInstanceVariableBindings)
            {
                binding.SetValue(idx);
                idx++;
            }
            this.ClassInstanceSize = idx;

            object[] clsInstVars = new object[idx];
            Array.Copy(this.ClassInstanceVariables, 0, clsInstVars, 0, Math.Min(this.ClassInstanceVariables.Length, clsInstVars.Length));
            this.ClassInstanceVariables = clsInstVars;
        }