Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="scfg"></param>
        /// <param name="aprot">If called for an agent activity - implemented protocol, otherwise null</param>
        /// <returns></returns>
        public bool Validate(SourceContext defaultContext)
        {
            HashSet <int> exclude = new HashSet <int>();

            foreach (GNode g in scfg.allNodes)
            {
                g.visited = false;
            }

            if (aprot != null && !aprot.ErrorReported)
            {
                aprot.syntax.validate(); aprot.syntax.convert();
                if (aprot.syntax.table != null)
                {
                    ptotable[0] = new Rules(aprot.syntax.table.GetServerEBNF(), aprot.syntax.testFunction.tests, "(" + aprot.Name + ") anonymous client");
                    scfg.entry.AddStateFor(ptotable[0].id, 0); //Entry point
                }
            }
            Queue <GNode> visitNext = new Queue <GNode>();

            visitNext.Enqueue(scfg.entry);
            GNode node = scfg.entry;

            while (visitNext.Count > 0)
            {
                node         = visitNext.Dequeue();
                node.visited = true;
                foreach (GNode next in node.successors)
                {
                    bool needtocopy = true;
                    if (next.astNode is ASSIGNMENT)
                    { // Interested in p := new A;
                        ASSIGNMENT nnode = next.astNode as ASSIGNMENT;
                        if (nnode.right_part is NEW && nnode.right_part.type is ACTIVITY_TYPE)
                        {
                            if (nnode.receiver is INSTANCE)
                            {
                                int id = ((INSTANCE)nnode.receiver).entity.unique;

                                ACTIVITY_TYPE acttype = nnode.right_part.type as ACTIVITY_TYPE;
                                if (((ACTIVITY_DECL)(acttype.activity)).prototype is PROTOCOL_DECL)
                                {
                                    if (!((ACTIVITY_DECL)(acttype.activity)).prototype.ErrorReported)
                                    {
                                        PROTOCOL_DECL eprot = ((ACTIVITY_DECL)(acttype.activity)).prototype as PROTOCOL_DECL;
                                        eprot.syntax.validate(); eprot.syntax.convert();
                                        if (eprot.syntax.table != null)
                                        {
                                            ptotable[id] = new Rules(eprot.syntax.table.GetClientEBNF(), eprot.syntax.testFunction.tests, "(" + eprot.name + ")" + ((INSTANCE)nnode.receiver).Name);
                                            next.AddStateFor(ptotable[id].id, 0);
                                            node.ForwardAllStatesExceptOneTo(next, ptotable[id].id);
                                            needtocopy = false;
                                        }
                                    }
                                }
                                else
                                { // Else it's ok. Do not trace this variable
                                    // Add to exclude set. All other cases will be treated with error: Not initialized dialog
                                    exclude.Add(id);
                                }
                            }
                            else
                            {
                                if (!nnode.ErrorReported)
                                {
                                    ERROR.ActivityVariableMustBeLocal(nnode.sourceContext);
                                }
                                nnode.ErrorReported = true;
                            }
                        }
                        else if ((nnode.right_part is CALL) &&
                                 (((CALL)nnode.right_part).callee is INSTANCE && (((CALL)nnode.right_part).type is ABSTRACT_ACTIVITY_TYPE || ((CALL)nnode.right_part).type is ACTIVITY_TYPE))
                                 )
                        {
                            int id = ((INSTANCE)((CALL)nnode.right_part).callee).entity.unique;
                            if (!exclude.Contains(id))
                            {
                                if (ptotable.ContainsKey(id))
                                {
                                    Rules rules = ptotable[id];
                                    foreach (int protocolState in node.GetStatesFor(rules.id))
                                    {
                                        int nextstate = protocolState;
                                        for (int i = 0; i < ((CALL)nnode.right_part).arguments.Length; i++)
                                        {
                                            EXPRESSION des       = ((CALL)nnode.right_part).arguments[i];
                                            int        savestate = nextstate;
                                            if ((nextstate = ValidateDataTransfer(rules, nextstate, false, des, true)) < 0)
                                            {
                                                if (!next.astNode.ErrorReported && !rules.errorReported)
                                                {
                                                    ERROR.ProtocolViolation(next.astNode.sourceContext, rules.ExpectedAtState(savestate, true));
                                                    next.astNode.ErrorReported = true;
                                                    rules.errorReported        = true;
                                                }
                                            }
                                            else if (nextstate == 0) // This was the last send/receive
                                            {
                                                nextstate = -1;
                                            }
                                        }
                                        { /* Process the receive */
                                            EXPRESSION des       = nnode.receiver;
                                            int        savestate = nextstate;
                                            if ((nextstate = ValidateDataTransfer(rules, nextstate, true, des, false)) < 0)
                                            {
                                                if (!next.astNode.ErrorReported && !rules.errorReported)
                                                {
                                                    ERROR.ProtocolViolation(next.astNode.sourceContext, rules.ExpectedAtState(savestate, true));
                                                    next.astNode.ErrorReported = true;
                                                    rules.errorReported        = true;
                                                }
                                            }
                                            else if (nextstate == 0) // This was the last send/receive
                                            {
                                                nextstate = -1;
                                            }
                                        }

                                        next.AddStateFor(rules.id, nextstate);
                                        node.ForwardAllStatesExceptOneTo(next, rules.id);
                                        needtocopy = false;
                                    }
                                }
                                else
                                {
                                    ERROR.AcceptCalledForInvalidDialog(nnode.sourceContext);
                                }
                            }
                        }
                    }
                    else if (next.astNode is ACCEPT)
                    {
                        ACCEPT anode = next.astNode as ACCEPT;
                        if (ptotable.ContainsKey(0))
                        {
                            Rules rules = ptotable[0];
                            foreach (int protocolState in node.GetStatesFor(rules.id))
                            {
                                int nextstate = protocolState;
                                for (int i = 0; i < anode.designators.Length; i++)
                                {
                                    EXPRESSION des       = anode.designators[i];
                                    int        savestate = nextstate;
                                    if ((nextstate = ValidateDataTransfer(rules, nextstate, false, des, false)) < 0)
                                    {
                                        if (!next.astNode.ErrorReported && !rules.errorReported)
                                        {
                                            ERROR.ProtocolViolation(next.astNode.sourceContext, rules.ExpectedAtState(savestate, false));
                                            next.astNode.ErrorReported = true;
                                            rules.errorReported        = true;
                                        }
                                    }
                                    else if (nextstate == 0) // This was the last send/receive
                                    {
                                        nextstate = -1;
                                    }
                                }
                                next.AddStateFor(rules.id, nextstate);
                                node.ForwardAllStatesExceptOneTo(next, rules.id);
                                needtocopy = false;
                            }
                        }
                    }
                    else if (next.astNode is REPLY)
                    {
                        REPLY rnode = next.astNode as REPLY;
                        if (ptotable.ContainsKey(0))
                        {
                            Rules rules = ptotable[0];
                            foreach (int protocolState in node.GetStatesFor(rules.id))
                            {
                                int nextstate = protocolState;
                                for (int i = 0; i < rnode.values_to_reply.Length; i++)
                                {
                                    EXPRESSION des       = rnode.values_to_reply[i];
                                    int        savestate = nextstate;
                                    if ((nextstate = ValidateDataTransfer(rules, nextstate, true, des, true)) < 0)
                                    {
                                        if (!next.astNode.ErrorReported && !rules.errorReported)
                                        {
                                            ERROR.ProtocolViolation(next.astNode.sourceContext, rules.ExpectedAtState(savestate, false));
                                            next.astNode.ErrorReported = true;
                                            rules.errorReported        = true;
                                        }
                                    }
                                    else if (nextstate == 0) // This was the last send/receive
                                    {
                                        nextstate = -1;
                                    }
                                }
                                next.AddStateFor(rules.id, nextstate);
                                node.ForwardAllStatesExceptOneTo(next, rules.id);
                                needtocopy = false;
                            }
                        }
                    }
                    else if (next.astNode is SEND_RECEIVE)
                    {
                        SEND_RECEIVE snode = next.astNode as SEND_RECEIVE;
                        if (snode.call.call.callee is INSTANCE)
                        {
                            int id = ((INSTANCE)snode.call.call.callee).entity.unique;
                            if (!exclude.Contains(id))
                            {
                                if (ptotable.ContainsKey(id))
                                {
                                    Rules rules = ptotable[id];
                                    foreach (int protocolState in node.GetStatesFor(rules.id))
                                    {
                                        int nextstate = protocolState;
                                        if (snode.call.call != null)
                                        {
                                            for (int i = 0; i < snode.call.call.arguments.Length; i++)
                                            {
                                                EXPRESSION des       = snode.call.call.arguments[i];
                                                int        savestate = nextstate;
                                                if ((nextstate = ValidateDataTransfer(rules, nextstate, false, des, true)) < 0)
                                                {
                                                    if (!next.astNode.ErrorReported && !rules.errorReported)
                                                    {
                                                        ERROR.ProtocolViolation(next.astNode.sourceContext, rules.ExpectedAtState(savestate, true));
                                                        next.astNode.ErrorReported = true;
                                                        rules.errorReported        = true;
                                                    }
                                                }
                                                else if (nextstate == 0) // This was the last send/receive
                                                {
                                                    nextstate = -1;
                                                }
                                            }
                                        }
                                        if (snode.leftParts != null)
                                        {
                                            for (int i = 0; i < snode.leftParts.Length; i++)
                                            {
                                                EXPRESSION des       = snode.leftParts[i];
                                                int        savestate = nextstate;
                                                if ((nextstate = ValidateDataTransfer(rules, nextstate, true, des, false)) < 0)
                                                {
                                                    if (!next.astNode.ErrorReported && !rules.errorReported)
                                                    {
                                                        ERROR.ProtocolViolation(next.astNode.sourceContext, rules.ExpectedAtState(savestate, true));
                                                        next.astNode.ErrorReported = true;
                                                        rules.errorReported        = true;
                                                    }
                                                }
                                                else if (nextstate == 0) // This was the last send/receive
                                                {
                                                    nextstate = -1;
                                                }
                                            }
                                        }
                                        next.AddStateFor(rules.id, nextstate);
                                        node.ForwardAllStatesExceptOneTo(next, rules.id);
                                        needtocopy = false;
                                    }
                                }
                                else
                                {
                                    ERROR.AcceptCalledForInvalidDialog(snode.sourceContext);
                                }
                            }
                        }
                        else
                        {
                            if (!snode.ErrorReported)
                            {
                                ERROR.ActivityVariableMustBeLocal(snode.sourceContext);
                            }
                            snode.ErrorReported = true;
                        }
                    }
                    else if (next.astNode is CALL_STMT)
                    {
                        CALL_STMT cnode = next.astNode as CALL_STMT;
                        if (cnode.call.callee is INSTANCE && (cnode.call.type is ABSTRACT_ACTIVITY_TYPE || cnode.call.type is ACTIVITY_TYPE))
                        {
                            int id = ((INSTANCE)cnode.call.callee).entity.unique;
                            if (!exclude.Contains(id))
                            {
                                if (ptotable.ContainsKey(id))
                                {
                                    Rules rules = ptotable[id];
                                    foreach (int protocolState in node.GetStatesFor(rules.id))
                                    {
                                        int nextstate = protocolState;
                                        if (cnode.call != null)
                                        {
                                            for (int i = 0; i < cnode.call.arguments.Length; i++)
                                            {
                                                EXPRESSION des       = cnode.call.arguments[i];
                                                int        savestate = nextstate;
                                                if ((nextstate = ValidateDataTransfer(rules, nextstate, false, des, true)) < 0)
                                                {
                                                    if (!next.astNode.ErrorReported && !rules.errorReported)
                                                    {
                                                        ERROR.ProtocolViolation(next.astNode.sourceContext, rules.ExpectedAtState(savestate, true));
                                                        next.astNode.ErrorReported = true;
                                                        rules.errorReported        = true;
                                                    }
                                                }
                                                else if (nextstate == 0) // This was the last send/receive
                                                {
                                                    nextstate = -1;
                                                }
                                            }
                                        }

                                        next.AddStateFor(rules.id, nextstate);
                                        node.ForwardAllStatesExceptOneTo(next, rules.id);
                                        needtocopy = false;
                                    }
                                }
                            }
                            else
                            {
                                ERROR.AcceptCalledForInvalidDialog(cnode.sourceContext);
                            }
                        }
                    }

                    if (needtocopy)
                    {
                        node.ForwardAllStatesTo(next);
                    }

                    if (!next.visited)
                    {
                        visitNext.Enqueue(next);
                    }
                }
            }
            // We leave the graph. All protocols in the last node must be in -1 state

            foreach (Rules rule in ptotable.Values)
            {
                foreach (int protocolState in node.GetStatesFor(rule.id))
                {
                    if (!ValidateEnd(rule, protocolState) && !rule.errorReported)
                    {
                        ERROR.ProtocolNotCompleted(new SourceContext(defaultContext.Document, defaultContext.EndPos - 3, defaultContext.EndPos), rule.name, rule.ExpectedAtState(protocolState, true));
                    }
                }
            }
            return(true);
        }