Пример #1
0
        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;
        }
Пример #2
0
        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;
        }