public override AstNode Visit(PropertyDefinition node) { // Get the name expression. Expression nameExpression = node.GetNameExpression(); if(nameExpression == null) return node; // Visit the name expression. nameExpression.SetHints(Expression.MemberHint); nameExpression.Accept(this); // Try to cast into a property. PropertyVariable contractProperty; DirectPropertySlot directProp = nameExpression.GetNodeValue() as DirectPropertySlot; if(directProp != null) contractProperty = directProp.Property; else contractProperty = nameExpression.GetNodeValue() as PropertyVariable; // It must be a property reference. if(contractProperty == null) Error(nameExpression, "expected property reference."); // Compare the property types. PropertyVariable property = node.GetProperty(); if(property.GetVariableType() != contractProperty.GetVariableType()) Error(nameExpression, "contracted property type mismatch."); // Instance the get accessor. if(contractProperty.GetAccessor != null) { if(property.GetAccessor == null) Error(nameExpression, "property implementation doesn't have a get accessor."); // Both accessors must be methods. if(!contractProperty.GetAccessor.IsMethod() || !property.GetAccessor.IsMethod()) Error(nameExpression, "property get accessor is not a static method."); // The accessors must match. if(!MatchFunction(contractProperty.GetAccessor.GetFunctionType(), property.GetAccessor.GetFunctionType(), 1)) Error(nameExpression, "get accessors have mismatching signatures."); // Bind the contract. Method impl = (Method)property.GetAccessor; impl.SetExplicitContract(contractProperty.GetAccessor); } else if(property.GetAccessor != null) Error(nameExpression, "property explicit contract doesn't have a get accessor."); // Instance the set accessor. if(contractProperty.SetAccessor != null) { if(property.SetAccessor == null) Error(nameExpression, "property implementation doesn't have a set accessor."); // Both accessors must be methods. if(!contractProperty.SetAccessor.IsMethod() || !property.SetAccessor.IsMethod()) Error(nameExpression, "property set accessor is not a static method."); // The accessors must match. if(!MatchFunction(contractProperty.SetAccessor.GetFunctionType(), property.SetAccessor.GetFunctionType(), 1)) Error(nameExpression, "set accessors have mismatching signatures."); // Bind the contract. Method impl = (Method)property.SetAccessor; impl.SetExplicitContract(contractProperty.SetAccessor); } else if(property.SetAccessor != null) Error(nameExpression, "property explicit contract doesn't have a set accessor."); return node; }
public override AstNode Visit(PropertyDefinition node) { // Check the property security. bool isUnsafe = (node.GetFlags() & MemberFlags.SecurityMask) == MemberFlags.Unsafe; if(isUnsafe) PushUnsafe(); // Generate a name for explicit contracts. if(node.GetNameExpression() != null) node.SetName(GenSym()); // Checks for indexers. if(node.GetNameExpression() == null) { if(node.GetName() == "this" && node.GetIndices() == null) Error(node, "indexers must have parameters."); else if(node.GetName() != "this" && node.GetIndices() != null) Error(node, "indexers name must be 'this'"); } // Use a special name for indexers. if(node.GetName() == "this") node.SetName("Op_Index"); // Find an existing property. ScopeMember oldProperty = currentContainer.FindMember(node.GetName()); if(oldProperty != null && !oldProperty.IsProperty()) Error(node, "trying to override something with a property."); // Visit the type expression. Expression typeExpr = node.GetPropertyType(); typeExpr.Accept(this); // Extract the meta type. IChelaType propType = typeExpr.GetNodeType(); propType = ExtractActualType(typeExpr, propType); // Use references for class/interface. if(propType.IsPassedByReference()) propType = ReferenceType.Create(propType); // Store the indices. List<IChelaType> indices = new List<IChelaType> (); AstNode index = node.GetIndices(); while(index != null) { // Visit the index. index.Accept(this); // Store his type. indices.Add(index.GetNodeType()); // Process the next index. index = index.GetNext(); } // Make sure it is the same property. PropertyVariable property = null; if(oldProperty != null) { // Compare the property types. property = (PropertyVariable) oldProperty; if(property.GetVariableType() != propType) Error(node, "trying to overwrite property."); // TODO: Check indices. // Avoid collisions. if(node.GetAccessor != null && property.GetAccessor != null) Error(node.GetAccessor, "multiples definitions."); if(node.SetAccessor != null && property.SetAccessor != null) Error(node.GetAccessor, "multiples definitions."); } else { // Create the property. property = new PropertyVariable(node.GetName(), node.GetFlags(), propType, indices.ToArray(), currentContainer); // Add it into the current scope. if(currentContainer.IsNamespace()) { Namespace space = (Namespace) currentContainer; space.AddMember(property); } else if(currentContainer.IsClass() || currentContainer.IsStructure() || currentContainer.IsInterface()) { Structure building = (Structure) currentContainer; building.AddProperty(property); } else Error(node, "a property cannot be defined here."); } // Store the property. node.SetProperty(property); // Set the property in the accessors. if(node.GetAccessor != null) { node.GetAccessor.SetProperty(property); node.GetAccessor.SetIndices(node.GetIndices()); } if(node.SetAccessor != null) { node.SetAccessor.SetProperty(property); node.SetAccessor.SetIndices(node.GetIndices()); } // Visit the accessors. VisitList(node.GetAccessors()); // Restore the property security. if(isUnsafe) PopUnsafe(); return node; }