예제 #1
0
        protected internal bool ValidateMethod(IDefinitionInstallerContext installer)
        {
            if (installer == null)
            {
                throw new ArgumentNullException();
            }
            // 1. Check if the selector is not complete garbage.
            if (String.IsNullOrWhiteSpace(this.Selector.Value))
            {
                return(installer.ReportError(this.Selector, InstallerErrors.MethodInvalidSelector));
            }
            // 2. Get the class.
            ClassBinding classBinding = installer.GetClassBinding(this.ClassName.Value);

            // 3. Check that such a binding exists
            if (classBinding == null)
            {
                return(installer.ReportError(this.ClassName, InstallerErrors.MethodInvalidClassName));
            }
            if (classBinding.Value == null)
            {
                throw new InvalidOperationException("Should have been set in ClassDefinition.CreataGlobalObject().");
            }

            // 3. Create the binding ... We allow duplicates and overwriting existing methods
            return(this.InternalValidateMethod(installer, classBinding.Value,
                                               new IntermediateCodeValidationErrorSink(this.MethodSourceCodeService, installer)));
        }
예제 #2
0
        /// <summary>
        /// Create the binding object (association) for the pool in the global name scope (system dictionary).
        /// </summary>
        /// <param name="installer">Context within which the binding is to be created.</param>
        /// <returns>Returns true if successful, otherwise false.</returns>
        protected internal override bool CreateGlobalBinding(IDefinitionInstallerContext installer)
        {
            if (installer == null)
            {
                throw new ArgumentNullException();
            }
            // 1. Check if the name is not complete garbage.
            if (!IronSmalltalk.Common.Utilities.ValidateIdentifier(this.Name.Value))
            {
                return(installer.ReportError(this.Name, InstallerErrors.PoolInvalidName));
            }
            // 2. Check if there is already a global with that name in the inner name scope
            Symbol name = installer.Runtime.GetSymbol(this.Name.Value);
            IDiscreteGlobalBinding existingBinding = installer.GetLocalGlobalBinding(name);

            if (existingBinding != null)
            {
                return(installer.ReportError(this.Name, InstallerErrors.PoolNameNotUnique));
            }
            // 3. No global defined in the inner scope, but check the scopes (inner or outer) for protected names like Object etc.
            if (installer.IsProtectedName(name))
            {
                return(installer.ReportError(this.Name, InstallerErrors.PoolNameProtected));
            }
            if (IronSmalltalk.Common.GlobalConstants.ReservedIdentifiers.Contains(this.Name.Value))
            {
                return(installer.ReportError(this.Name, InstallerErrors.PoolReservedName));
            }

            // 4. OK ... create a binding - so far pointing to null.
            installer.AddPoolBinding(new PoolBinding(name));
            return(true);
        }
예제 #3
0
        protected internal override bool ValidateInitializer(IDefinitionInstallerContext installer)
        {
            if (installer == null)
            {
                throw new ArgumentNullException();
            }
            // 2. Get the global.
            GlobalVariableOrConstantBinding globalBinding = installer.GetGlobalVariableOrConstantBinding(this.GlobalName.Value);
            ClassBinding classBinding = installer.GetClassBinding(this.GlobalName.Value);

            // 3. Check that such a binding exists ... but not both
            if (!((globalBinding == null) ^ (classBinding == null)))
            {
                return(installer.ReportError(this.GlobalName, InstallerErrors.GlobalInvalidName));
            }
            if ((classBinding != null) && (classBinding.Value == null))
            {
                throw new InvalidOperationException("Should have been set in ClassDefinition.CreataGlobalObject().");
            }

            if (classBinding != null)
            {
                return(this.Factory.ValidateClassInitializer(this, classBinding.Value, installer,
                                                             new IntermediateCodeValidationErrorSink(this.MethodSourceCodeService, installer)));
            }

            if (globalBinding.IsConstantBinding && globalBinding.HasBeenSet)
            {
                return(installer.ReportError(this.GlobalName, InstallerErrors.GlobalIsConstant));
            }

            return(this.Factory.ValidateGlobalInitializer(this, installer,
                                                          new IntermediateCodeValidationErrorSink(this.MethodSourceCodeService, installer)));
        }
        protected internal override bool ValidateInitializer(IDefinitionInstallerContext installer)
        {
            if (installer == null)
            {
                throw new ArgumentNullException();
            }
            // 1. Check if the name is not complete garbage.
            if (!IronSmalltalk.Common.Utilities.ValidateIdentifier(this.VariableName.Value))
            {
                return(installer.ReportError(this.VariableName, InstallerErrors.PoolVarInvalidName));
            }
            // 2. Get the pool dictionary.
            PoolBinding poolBinding = installer.GetPoolBinding(this.PoolName.Value);

            // 3. Check that such a binding exists
            if (poolBinding == null)
            {
                return(installer.ReportError(this.PoolName, InstallerErrors.PoolInvalidPoolName));
            }
            if (poolBinding.Value == null)
            {
                throw new InvalidOperationException("Should have been set in PoolDefinition.CreataGlobalObject().");
            }

            Symbol varName = installer.Runtime.GetSymbol(this.VariableName.Value);
            PoolVariableOrConstantBinding poolItemBinding;

            poolBinding.Value.TryGetValue(varName, out poolItemBinding);
            if (poolItemBinding == null)
            {
                return(installer.ReportError(this.VariableName, InstallerErrors.PoolVarInvalidName));
            }

            if (poolItemBinding.IsConstantBinding && poolItemBinding.HasBeenSet)
            {
                return(installer.ReportError(this.VariableName, InstallerErrors.PoolItemIsConstant));
            }

            return(this.Factory.ValidatePoolVariableInitializer(this, poolBinding.Value, installer,
                                                                new IntermediateCodeValidationErrorSink(this.MethodSourceCodeService, installer)));
        }
예제 #5
0
        /// <summary>
        /// Create a binding object (association) for the pool variable in the pool that owns it.
        /// </summary>
        /// <param name="installer">Context within which the binding is to be created.</param>
        /// <returns>Returns true if successful, otherwise false.</returns>
        protected internal override bool CreatePoolVariableBinding(IDefinitionInstallerContext installer)
        {
            if (installer == null)
            {
                throw new ArgumentNullException();
            }
            // 1. Check if the name is not complete garbage.
            if (!IronSmalltalk.Common.Utilities.ValidateIdentifier(this.VariableName.Value))
            {
                return(installer.ReportError(this.VariableName, InstallerErrors.PoolVarInvalidName));
            }
            // 2. Get the pool dictionary.
            PoolBinding poolBinding = installer.GetPoolBinding(this.PoolName.Value);

            // 3. Check that such a binding exists
            if (poolBinding == null)
            {
                return(installer.ReportError(this.PoolName, InstallerErrors.PoolInvalidPoolName));
            }
            if (poolBinding.Value == null)
            {
                throw new InvalidOperationException("Should have been set in PoolDefinition.CreataGlobalObject().");
            }
            // 4. Check for reserved keywords
            if (IronSmalltalk.Common.GlobalConstants.ReservedIdentifiers.Contains(this.VariableName.Value))
            {
                return(installer.ReportError(this.VariableName, InstallerErrors.PoolVarReservedName));
            }
            // 5. Check that no duplicate exists.
            Symbol varName = installer.Runtime.GetSymbol(this.VariableName.Value);
            PoolVariableOrConstantBinding existing;

            poolBinding.Value.TryGetValue(varName, out existing);
            if (existing != null)
            {
                return(installer.ReportError(this.VariableName, InstallerErrors.PoolItemNameNotUnique));
            }
            // 6. Create the binding
            poolBinding.Value.Add(new PoolVariableBinding(varName));
            return(true);
        }
예제 #6
0
        /// <summary>
        /// Validate that the definition of the class object does not break any rules set by the Smalltalk standard.
        /// </summary>
        /// <param name="installer">Context within which the validation is to be performed.</param>
        /// <returns>Returns true if successful, otherwise false.</returns>
        protected internal override bool ValidateObject(IDefinitionInstallerContext installer)
        {
            if (installer == null)
            {
                throw new ArgumentNullException();
            }
            // 1. Get the binding to the global
            Symbol       name    = installer.Runtime.GetSymbol(this.Name.Value);
            ClassBinding binding = installer.GetLocalClassBinding(name);

            // 2. Check consistency that we didn't mess up in the implementation.
            if (binding == null)
            {
                throw new InvalidOperationException("Should have found a binding, because CreateGlobalBinding() created it!");
            }
            if (binding.Value == null)
            {
                throw new InvalidOperationException("Should not be an empty binding, because CreateGlobalObject() just created it!");
            }
            // 3. Get the class object.
            SmalltalkClass cls = binding.Value;
            // 4. Validate that superclass is correct
            List <Symbol> classes = new List <Symbol>();

            classes.Add(cls.Name);
            SmalltalkClass tmp = cls.Superclass;

            while (tmp != null)
            {
                if (classes.IndexOf(tmp.Name) != -1)
                {
                    return(installer.ReportError(this.SuperclassName, String.Format(
                                                     InstallerErrors.ClassCircularReference, this.SuperclassName.Value, this.Name.Value)));
                }
                classes.Add(tmp.Name);
                tmp = tmp.Superclass;
            }

            if (cls.InstanceState != SmalltalkClass.InstanceStateEnum.ByteIndexable)
            {
                tmp = cls;
                while (tmp != null)
                {
                    if (tmp.InstanceState == SmalltalkClass.InstanceStateEnum.ByteIndexable)
                    {
                        return(installer.ReportError(this.InstanceState, InstallerErrors.ClassCannotChangeInstanceState));
                    }
                    tmp = tmp.Superclass;
                }
            }

            foreach (PoolBinding pool in cls.ImportedPoolBindings)
            {
                if (pool.Value == null)
                {
                    SourceReference <string> src = this.ImportedPoolNames.SingleOrDefault(sr => sr.Value == pool.Name.Value);
                    if (src == null)
                    {
                        throw new InvalidOperationException("Should not be null, cause we just added this pool in CreateGlobalObject().");
                    }
                    return(installer.ReportError(src, InstallerErrors.ClassMissingPoolDefinition));
                }
            }

            // NB: We must give some source reference, but since we don't have for the whole class, we use the name.
            installer.RegisterNewClass(cls, this.Name);

            return(true); // OK
        }
예제 #7
0
        /// <summary>
        /// Create the class object (and sets the value of the binding).
        /// </summary>
        /// <param name="installer">Context within which the class is to be created.</param>
        /// <returns>Returns true if successful, otherwise false.</returns>
        protected internal override bool CreateGlobalObject(IDefinitionInstallerContext installer)
        {
            if (installer == null)
            {
                throw new ArgumentNullException();
            }
            // 1. Get the binding to the global
            Symbol       name    = installer.Runtime.GetSymbol(this.Name.Value);
            ClassBinding binding = installer.GetLocalClassBinding(name);

            // 2. Check consistency that we didn't mess up in the implementation.
            if (binding == null)
            {
                throw new InvalidOperationException("Should have found a binding, because CreateGlobalBinding() created it!");
            }
            if (binding.Value != null)
            {
                throw new InvalidOperationException("Should be an empty binding, because CreateGlobalBinding() complained if one already existed!");
            }

            // 3. Prepare stuff ....
            SmalltalkClass.InstanceStateEnum instanceState = this.InstanceState.Value;
            ClassBinding superclass;

            if (this.SuperclassName.Value.Length == 0)
            {
                superclass = null; // Object has no superclass
            }
            else
            {
                superclass = installer.GetClassBinding(this.SuperclassName.Value);
                if (superclass == null)
                {
                    return(installer.ReportError(this.SuperclassName, InstallerErrors.ClassInvalidSuperclass));
                }
            }

            // Create the collection of class, class-instance, instance variables and imported pools
            BindingDictionary <InstanceVariableBinding>      instVars      = new BindingDictionary <InstanceVariableBinding>(installer.Runtime);
            DiscreteBindingDictionary <ClassVariableBinding> classVars     = new DiscreteBindingDictionary <ClassVariableBinding>(installer.Runtime, this.ClassVariableNames.Count());
            BindingDictionary <ClassInstanceVariableBinding> classInstVars = new BindingDictionary <ClassInstanceVariableBinding>(installer.Runtime);
            DiscreteBindingDictionary <PoolBinding>          pools         = new DiscreteBindingDictionary <PoolBinding>(installer.Runtime);

            // Validate class variable names ...
            foreach (SourceReference <string> identifier in this.ClassVariableNames)
            {
                Symbol varName = installer.Runtime.GetSymbol(identifier.Value);
                if (!IronSmalltalk.Common.Utilities.ValidateIdentifier(identifier.Value))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassClassVariableNotIdentifier));
                }
                if (classVars.Any <ClassVariableBinding>(varBinding => varBinding.Name == varName))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassClassVariableNotUnique));
                }
                classVars.Add(new ClassVariableBinding(varName));
            }
            // Validate instance variable names ...
            foreach (SourceReference <string> identifier in this.InstanceVariableNames)
            {
                Symbol varName = installer.Runtime.GetSymbol(identifier.Value);
                if (!IronSmalltalk.Common.Utilities.ValidateIdentifier(identifier.Value))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassInstanceVariableNotIdentifier));
                }
                if (((IEnumerable <InstanceVariableBinding>)instVars).Any(varBinding => varBinding.Name == varName))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassInstanceVariableNotUnique));
                }
                if (classVars.Any <ClassVariableBinding>(varBinding => varBinding.Name == varName))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassInstanceOrClassVariableNotUnique));
                }
                instVars.Add(new InstanceVariableBinding(varName));
            }
            // Validate class instance variable names ...
            foreach (SourceReference <string> identifier in this.ClassInstanceVariableNames)
            {
                Symbol varName = installer.Runtime.GetSymbol(identifier.Value);
                if (!IronSmalltalk.Common.Utilities.ValidateIdentifier(identifier.Value))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassClassInstanceVariableNotIdentifier));
                }
                if (classInstVars.Any <ClassInstanceVariableBinding>(varBinding => varBinding.Name == varName))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassClassInstanceVariableNotUnique));
                }
                if (classVars.Any <ClassVariableBinding>(varBinding => varBinding.Name == varName))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassClassInstanceOrClassVariableNotUnique));
                }
                classInstVars.Add(new ClassInstanceVariableBinding(varName));
            }
            // Validate imported pool names ...
            foreach (SourceReference <string> identifier in this.ImportedPoolNames)
            {
                Symbol varName = installer.Runtime.GetSymbol(identifier.Value);
                if (!IronSmalltalk.Common.Utilities.ValidateIdentifier(identifier.Value))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassImportedPoolNotIdentifier));
                }
                if (pools.Any <PoolBinding>(varBinding => varBinding.Name == varName))
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassImportedPoolNotUnique));
                }
                PoolBinding pool = installer.GetPoolBinding(varName);
                if (pool == null)
                {
                    return(installer.ReportError(identifier, InstallerErrors.ClassImportedPoolNotDefined));
                }
                pools.Add(pool);
            }

            // 4. Finally, create the behavior object
            binding.SetValue(new SmalltalkClass(
                                 installer.Runtime, binding.Name, superclass, instanceState, instVars, classVars, classInstVars, pools));
            return(true);
        }