Ejemplo n.º 1
0
        public override AstNode Visit(FieldDefinition node)
        {
            // Push the unsafe context.
            bool isUnsafe = (node.GetFlags() & MemberFlags.SecurityMask) == MemberFlags.Unsafe;
            if(isUnsafe)
                PushUnsafe();

            // Get the type node.
            Expression typeExpression = node.GetTypeNode();

            // Visit the type node.
            typeExpression.Accept(this);

            // Get the type of the type expression.
            IChelaType type = typeExpression.GetNodeType();
            type = ExtractActualType(typeExpression, type);

            // Check field type security.
            if(type.IsUnsafe())
                UnsafeError(node, "safe field with unsafe type.");

            // Class/interfaces instances are held by reference.
            if(type.IsPassedByReference())
                type = ReferenceType.Create(type);

            // Constants are always static.
            if(type.IsConstant())
                node.SetFlags((node.GetFlags() & ~MemberFlags.InstanceMask) | MemberFlags.Static);

            // Process the declarations.
            FieldDeclaration decl = node.GetDeclarations();
            while(decl != null)
            {
                // Find an existent member.
                ScopeMember oldField = currentContainer.FindMember(decl.GetName());
                if(oldField != null)
                    Error(node, "already declared a member with the same name.");

                // Create the field.
                FieldVariable field = new FieldVariable(decl.GetName(), node.GetFlags(), type, currentContainer);
                field.Position = decl.GetPosition();
                decl.SetVariable(field);
                decl.SetNodeType(type);

                // Add the field into the scope.
                if(currentContainer.IsStructure() || currentContainer.IsClass())
                {
                    // Add the field.
                    Structure building = (Structure)currentContainer;
                    building.AddField(field);
                }
                else if(currentContainer.IsNamespace())
                {
                    // Make sure its a global variable.
                    if(!field.IsStatic())
                        Error(node, "namespaces only can have static fields.");

                    Namespace space = (Namespace)currentContainer;
                    space.AddMember(field);
                }
                else
                {
                    Error(node, "a field must be declared inside an structure or class.");
                }

                // Process the next declaration.
                decl = (FieldDeclaration)decl.GetNext();
            }

            if(isUnsafe)
                PopUnsafe();

            return node;
        }