public override AstNode Visit(PropertyDefinition node) { // Add the parent static flag. if(currentContainer.IsStatic()) { MemberFlags oldInstance = node.GetFlags() & MemberFlags.InstanceMask; if(oldInstance == MemberFlags.Static || oldInstance == MemberFlags.Instanced) { MemberFlags flags = node.GetFlags() & ~MemberFlags.InstanceMask; node.SetFlags(flags | MemberFlags.Static); } else Error(node, "static class member cannot {0}.", oldInstance.ToString().ToLower()); } // Add the parent unsafe flag. if(IsUnsafe) { MemberFlags flags = node.GetFlags() & ~MemberFlags.SecurityMask; node.SetFlags(flags | MemberFlags.Unsafe); } // Link the accessors. AstNode acc = node.GetAccessors(); while(acc != null) { PropertyAccessor pacc = (PropertyAccessor)acc; if(pacc.IsGetAccessor()) { if(node.GetAccessor != null) Error(node, "a property only can have one get accessor."); node.GetAccessor = (GetAccessorDefinition)pacc; } else { if(node.SetAccessor != null) Error(node, "a property only can have one set accessor."); node.SetAccessor = (SetAccessorDefinition)pacc; } acc = acc.GetNext(); } 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; }