示例#1
0
        public override AstNode Visit(SetAccessorDefinition node)
        {
            PropertyVariable property = node.GetProperty();

            if(node.GetChildren() == null && property.SetAccessor != null)
                return node;

            if(node.GetChildren() != null && property.SetAccessor != null)
                Error(node, "multiples definitions of the set accessor.");

            // Build the property flags.
            MemberFlags flags = node.GetFlags();
            if(flags == MemberFlags.ImplicitVis)
            {
                flags = property.GetFlags();
            }
            else
            {
                // TODO: Check compatibility.
                flags |= property.GetFlags() & ~MemberFlags.VisibilityMask;
            }

            // Get the instance type.
            MemberFlags instanceFlags = MemberFlags.InstanceMask & flags;

            // Abstract properties cannot have a body.
            if((instanceFlags == MemberFlags.Abstract ||
               instanceFlags == MemberFlags.Contract) && node.GetChildren() != null)
                Error(node, "abstract properties cannot have a definition body.");

            // Create the set accesor.
            if(property.SetAccessor == null)
            {
                // Create the argument list.
                List<IChelaType> arguments = new List<IChelaType> ();

                // Add the this argument.
                IChelaType selfType = null;
                if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
                {
                    Structure building = (Structure) currentContainer;
                    if(instanceFlags != MemberFlags.Static)
                    {
                        // Instance the building.
                        building = building.GetSelfInstance();

                        // Create the self parameter.
                        selfType = ReferenceType.Create(building);
                        arguments.Add(selfType);
                    }
                }

                // Append the indices.
                foreach(IChelaType indexType in property.Indices)
                    arguments.Add(indexType);

                // Add the value argument.
                arguments.Add(property.GetVariableType());

                // Create the function type.
                FunctionType functionType = FunctionType.Create(ChelaType.GetVoidType(), arguments, false);

                // Create the function.
                Function accessor;
                if(selfType != null)
                    accessor = new Method("set_" + property.GetName(), flags, currentContainer);
                else
                    accessor = new Function("set_" + property.GetName(), flags, currentContainer);

                // Set the arguments.
                accessor.SetFunctionType(functionType);

                // Set the function position.
                accessor.Position = node.GetPosition();

                // Store the function in the property.
                property.SetAccessor = accessor;

                // Store the function in his scope.
                if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
                {
                    Structure building = (Structure)currentContainer;
                    building.AddFunction("set_" + property.GetName(), accessor);
                }
                else if(currentContainer.IsNamespace())
                {
                    Namespace space = (Namespace)currentContainer;
                    space.AddMember(accessor);
                }
                else
                {
                    Error(node, "a property cannot be declared here.");
                }

                // If there's a body, declare the "argument" variables.
                if(node.GetChildren() != null)
                {
                    LexicalScope scope = CreateLexicalScope(node, accessor);

                    // Add the "this" local.
                    if(selfType != null)
                        new ArgumentVariable(0, "this", scope, selfType);

                    // Add the "value" local
                    LocalVariable valueVar = new LocalVariable("value", scope, property.GetVariableType());
                    node.SetValueLocal(valueVar);

                    // Add the indices variables.
                    AstNode index = node.GetIndices();
                    List<LocalVariable> indexerVars = new List<LocalVariable> ();
                    while(index != null)
                    {
                        // Create the local
                        LocalVariable local = new LocalVariable(index.GetName(), scope, index.GetNodeType());
                        indexerVars.Add(local);

                        // Process the next.
                        index = index.GetNext();
                    }
                    node.SetIndexerVariables(indexerVars);
                    node.SetScope(scope);
                }
            }
            else
            {
                // Check for declaration compatibility.
                if(flags != property.SetAccessor.GetFlags())
                    Error(node, "incompatible set accessor declarations.");
            }

            // Set the node function to the accessor.
            node.SetFunction(property.SetAccessor);

            return node;
        }