Example #1
0
        public override AstNode Visit(EventAccessorDefinition node)
        {
            EventVariable eventVariable = node.GetEvent();

            // Build the event flags.
            MemberFlags flags = node.GetFlags();
            if(flags == MemberFlags.ImplicitVis)
            {
                flags = eventVariable.GetFlags();
            }
            else
            {
                // TODO: Check compatibility.
                flags |= eventVariable.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 events cannot have a definition body.");

            // 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 argument.
                    selfType = ReferenceType.Create(building);
                    arguments.Add(selfType);
                }
            }

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

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

            // Build the function name.
            string functionName = node.GetName() + "_" + eventVariable.GetName();

            // Create the function.
            Function accessor;
            if(selfType != null)
                accessor = new Method(functionName, flags, currentContainer);
            else
                accessor = new Function(functionName, flags, currentContainer);

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

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

            // Store the function in the event.
            if(node.GetName() == "add")
                eventVariable.AddModifier = accessor;
            else
                eventVariable.RemoveModifier = accessor;

            // Store the function in his scope.
            if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
            {
                Structure building = (Structure)currentContainer;
                building.AddFunction(functionName, accessor);
            }
            else if(currentContainer.IsNamespace())
            {
                Namespace space = (Namespace)currentContainer;
                space.AddMember(accessor);
            }
            else
            {
                Error(node, "an event 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, eventVariable.GetVariableType());
                node.SetValueLocal(valueVar);

                // Store the scope
                node.SetScope(scope);
            }

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

            return node;
        }