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))); }
/// <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); }
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))); }
/// <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); }
/// <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 }
/// <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); }