From b95a9c2d23c4bfba84dfac8683c47153d598e09f Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Fri, 8 Aug 2014 20:49:30 +0200 Subject: Be more explicit as to why a configuration is invalid --- src/uscxml/Interpreter.cpp | 40 +++++++++++++++++---------------- src/uscxml/debug/SCXMLDotWriter.cpp | 45 ++++++++++++++++++++----------------- src/uscxml/transform/ChartToFSM.cpp | 28 ++++++++++++++++------- src/uscxml/transform/ChartToFSM.h | 3 ++- 4 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index b9b5d94..7556961 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -2648,24 +2648,16 @@ bool InterpreterImpl::isLegalConfiguration(const std::list& config) */ bool InterpreterImpl::isLegalConfiguration(const NodeSet& config) { -#if VERBOSE - std::cout << "Checking whether {"; - std::string seperator; - for (int i = 0; i < config.size(); i++) { - std::cout << seperator << ATTR(config[i], "id"); - seperator = ", "; - } - std::cout << "} is legal" << std::endl; -#endif - // The configuration contains exactly one child of the element. NodeSet scxmlChilds = getChildStates(_scxml); - bool foundScxmlChild = false; + Node foundScxmlChild; for (int i = 0; i < scxmlChilds.size(); i++) { if (isMember(scxmlChilds[i], config)) { - if (foundScxmlChild) + if (foundScxmlChild) { + LOG(ERROR) << "Invalid configuration: Multiple childs of scxml root are active '" << ATTR_CAST(foundScxmlChild, "id") << "' and '" << ATTR_CAST(scxmlChilds[i], "id") << "'"; return false; - foundScxmlChild = true; + } + foundScxmlChild = scxmlChilds[i]; } } if (!foundScxmlChild) @@ -2679,8 +2671,10 @@ bool InterpreterImpl::isLegalConfiguration(const NodeSet& config) { break; } } - if (!foundAtomicState) + if (!foundAtomicState) { + LOG(ERROR) << "Invalid configuration: No atomic state is active"; return false; + } // When the configuration contains an atomic state, it contains all of its and ancestors. for (int i = 0; i < config.size(); i++) { @@ -2690,8 +2684,10 @@ bool InterpreterImpl::isLegalConfiguration(const NodeSet& config) { if (isState(Element(parent)) && (iequals(LOCALNAME(parent), "state") || iequals(LOCALNAME(parent), "parallel"))) { - if (!isMember(parent, config)) + if (!isMember(parent, config)) { + LOG(ERROR) << "Invalid configuration: atomic state '" << ATTR_CAST(config[i], "id") << "' is active, but parent '" << ATTR_CAST(parent, "id") << "' is not"; return false; + } } } } @@ -2701,19 +2697,24 @@ bool InterpreterImpl::isLegalConfiguration(const NodeSet& config) { for (int i = 0; i < config.size(); i++) { Element configElem(config[i]); if (!isAtomic(configElem) && !isParallel(configElem)) { - bool foundChildState = false; + Node foundChildState; //std::cout << config[i] << std::endl; NodeSet childs = getChildStates(config[i]); for (int j = 0; j < childs.size(); j++) { //std::cout << childs[j] << std::endl; if (isMember(childs[j], config)) { - if (foundChildState) + if (foundChildState) { + LOG(ERROR) << "Invalid configuration: Multiple childs of compound '" << ATTR_CAST(config[i], "id") + << "' are active '" << ATTR_CAST(foundChildState, "id") << "' and '" << ATTR_CAST(childs[j], "id") << "'"; return false; - foundChildState = true; + } + foundChildState = childs[j]; } } - if (!foundChildState) + if (!foundChildState) { + LOG(ERROR) << "Invalid configuration: No childs of compound '" << ATTR_CAST(config[i], "id") << "' are active"; return false; + } } } @@ -2723,6 +2724,7 @@ bool InterpreterImpl::isLegalConfiguration(const NodeSet& config) { NodeSet childs = getChildStates(config[i]); for (int j = 0; j < childs.size(); j++) { if (!isMember(childs[j], config) && !isHistory(Element(childs[j]))) { + LOG(ERROR) << "Invalid configuration: Not all children of parallel '" << ATTR_CAST(config[i], "id") << "' are active i.e. '" << ATTR_CAST(childs[j], "id") << "' is not"; return false; } } diff --git a/src/uscxml/debug/SCXMLDotWriter.cpp b/src/uscxml/debug/SCXMLDotWriter.cpp index 1b9555e..5c15dbd 100644 --- a/src/uscxml/debug/SCXMLDotWriter.cpp +++ b/src/uscxml/debug/SCXMLDotWriter.cpp @@ -124,26 +124,26 @@ void SCXMLDotWriter::writeTo(std::ostream& os) { continue; } - os << getPrefix() << "\"" << edgeIter->from << "\""; + os << getPrefix() << "\"" << portEscape(edgeIter->from) << "\""; if (edgeIter->fromPort.size() > 0) { - os << std::string(":\"") + edgeIter->fromPort + "\":e"; + os << std::string(":\"") + portEscape(edgeIter->fromPort) + "\":e"; } else { os << ":__name"; } os << " -> "; if (_histories.find(edgeIter->to) != _histories.end()) { - os << getPrefix() << "\"" << _histories.find(edgeIter->to)->second.to << "\""; + os << getPrefix() << "\"" << portEscape(_histories.find(edgeIter->to)->second.to) << "\""; if (_histories.find(edgeIter->to)->second.toPort.size() > 0) { - os << std::string(":\"") + _histories.find(edgeIter->to)->second.toPort + "\""; + os << std::string(":\"") + portEscape(_histories.find(edgeIter->to)->second.toPort) + "\""; } else { os << ":__name"; } } else { - os << getPrefix() << "\"" << edgeIter->to << "\""; + os << getPrefix() << "\"" << portEscape(edgeIter->to) << "\""; if (edgeIter->toPort.size() > 0) { - os << std::string(":\"") + edgeIter->toPort + "\""; + os << std::string(":\"") + portEscape(edgeIter->toPort) + "\""; } else { os << ":__name"; } @@ -274,7 +274,7 @@ void SCXMLDotWriter::writeStateElement(std::ostream& os, const Element" << std::endl; @@ -294,7 +294,7 @@ void SCXMLDotWriter::writeStateElement(std::ostream& os, const Element histories = InterpreterImpl::filterChildElements(_xmlNSPrefix + "history", stateElem); for (int i = 0; i < histories.size(); i++) { - os << " history: " << ATTR_CAST(histories[i], "id") << "" << std::endl; + os << " history: " << ATTR_CAST(histories[i], "id") << "" << std::endl; } @@ -772,7 +772,10 @@ std::string SCXMLDotWriter::getDetailedLabel(const Element& elem, i std::string SCXMLDotWriter::portEscape(const std::string& text) { std::string escaped(text); boost::replace_all(escaped, ".", "-"); - return text; + boost::replace_all(escaped, "{", "-"); + boost::replace_all(escaped, "}", "-"); + boost::replace_all(escaped, ":", "-"); + return escaped; } std::string SCXMLDotWriter::dotEscape(const std::string& text) { @@ -840,17 +843,17 @@ std::string SCXMLDotWriter::idForNode(const Node& node) { if (node.getNodeType() == Node_base::ELEMENT_NODE) { Element elem = (Element)node; - if (InterpreterImpl::isFinal(elem) && _isFlat) { - // ignore visited and history with final elements - FlatStateIdentifier flatId(elem.getAttribute("id")); - - std::stringstream activeSS; - activeSS << "active-"; - for (std::list::const_iterator activeIter = flatId.getActive().begin(); activeIter != flatId.getActive().end(); activeIter++) { - activeSS << *activeIter << "-"; - } - return activeSS.str(); - } +// if (InterpreterImpl::isFinal(elem) && _isFlat) { +// // ignore visited and history with final elements +// FlatStateIdentifier flatId(elem.getAttribute("id")); +// +// std::stringstream activeSS; +// activeSS << "active-"; +// for (std::list::const_iterator activeIter = flatId.getActive().begin(); activeIter != flatId.getActive().end(); activeIter++) { +// activeSS << *activeIter << "-"; +// } +// return activeSS.str(); +// } if (elem.hasAttribute("name")) { elemId = elem.getAttribute("name"); diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp index 073805f..0aac811 100644 --- a/src/uscxml/transform/ChartToFSM.cpp +++ b/src/uscxml/transform/ChartToFSM.cpp @@ -206,7 +206,7 @@ InterpreterState FlatteningInterpreter::interpret() { GlobalState::gIndex = 0; _start = new GlobalState(_configuration, _alreadyEntered, _historyValue, _nsInfo.xmlNSPrefix); _globalConf[_start->stateId] = _start; - _globalConf[_start->stateId]->index = GlobalState::gIndex++; + _globalConf[_start->stateId]->index = toStr(GlobalState::gIndex++); NodeSet initialTransitions; @@ -473,7 +473,7 @@ void FlatteningInterpreter::explode() { } _globalConf[globalState->stateId] = globalState; - _globalConf[globalState->stateId]->index = GlobalState::gIndex++; + _globalConf[globalState->stateId]->index = toStr(GlobalState::gIndex++); assert(isLegalConfiguration(configuration)); if(_globalConf[globalState->stateId]->isFinal) @@ -568,7 +568,10 @@ void FlatteningInterpreter::explode() { if (tthread::chrono::system_clock::now() - _lastTimeStamp > 1000) { _lastTimeStamp = tthread::chrono::system_clock::now(); // std::cout << globalState->stateId << " [" << nrElements << "]: " << std::endl; - std::cout << _perfTotal << " [" << _perfProcessed << "/sec]" << std::endl; + std::cout << "States: " << _globalConf.size() << " - "; + std::cout << "Tested: " << _perfTotal << " [" << _perfProcessed << "/sec] - "; + std::cout << "Current Complexity: 2**" << nrElements << " = " << pow(2.0, static_cast(nrElements)); + std::cout << std::endl; _perfProcessed = 0; } @@ -667,10 +670,16 @@ NEXT_DEPTH: _currGlobalTransition = *transListIter; microstep((*transListIter)->transitions); if (!isLegalConfiguration(_configuration)) { - std::cout << "invalid configuration from " << globalState->stateId << std::endl; + FlatStateIdentifier fromState(configuration, alreadyEntered, historyValue); + FlatStateIdentifier toState(_configuration, _alreadyEntered, _historyValue); + std::cerr << "invalid configuration after transition " << std::endl + << "from \t" << fromState.getStateId() << std::endl + << "to \t" << toState.getStateId() << std::endl + << "via ------" << std::endl; for (int i = 0; i < (*transListIter)->transitions.size(); i++) { - std::cout << (*transListIter)->transitions[i] << std::endl; + std::cerr << (*transListIter)->transitions[i] << std::endl; } + std::cerr << "----------" << std::endl; assert(false); } explode(); @@ -752,13 +761,12 @@ Node FlatteningInterpreter::globalStateToNode(GlobalState* globalSt Element state = _flatDoc.createElementNS(_nsInfo.nsURL, "state"); _nsInfo.setPrefix(state); + state.setAttribute("ref", globalState->index); state.setAttribute("id", globalState->stateId); if (globalState->isFinal) state.setAttribute("final", "true"); -// state.setAttribute("index", toStr(globalState->index)); - std::list transitionList; for (std::map::iterator outIter = globalState->outgoing.begin(); outIter != globalState->outgoing.end(); @@ -769,10 +777,13 @@ Node FlatteningInterpreter::globalStateToNode(GlobalState* globalSt transitionList = sortTransitions(transitionList); // std::cout << "/////////////////" << std::endl; + size_t index = 0; for (std::list::iterator outIter = transitionList.begin(); outIter != transitionList.end(); outIter++) { + (*outIter)->index = globalState->index + ":" + toStr(index); state.appendChild(globalTransitionToNode(*outIter)); + index++; } // std::cout << "/////////////////" << std::endl; @@ -786,6 +797,8 @@ Node FlatteningInterpreter::globalTransitionToNode(GlobalTransition Element transition = _flatDoc.createElementNS(_nsInfo.nsURL, "transition"); _nsInfo.setPrefix(transition); +// transition.setAttribute("ref", globalTransition->index); + if (!globalTransition->isEventless) { transition.setAttribute("event", globalTransition->eventDesc); } @@ -822,7 +835,6 @@ Node FlatteningInterpreter::globalTransitionToNode(GlobalTransition transition.setAttribute("prioPerLevel", nrSS.str()); #endif - transition.setAttribute("id", globalTransition->transitionId); // std::cout << " firstPerLevel:" << feSS.str() << " " << globalTransition->transitionId << std::endl; // std::cout << "event: " << globalTransition->eventDesc << " firstPerLevel:" << feSS.str() << " numberPerLevel:" << nrSS.str() << " prioPerLevel:" << prSS.str() << " " << globalTransition->transitionId << std::endl; diff --git a/src/uscxml/transform/ChartToFSM.h b/src/uscxml/transform/ChartToFSM.h index 5ee5c8e..64b3640 100644 --- a/src/uscxml/transform/ChartToFSM.h +++ b/src/uscxml/transform/ChartToFSM.h @@ -51,7 +51,7 @@ public: static int gIndex; - int index; + std::string index; bool isFinal; }; @@ -99,6 +99,7 @@ public: std::string source; std::string destination; + std::string index; protected: std::list getCommonEvents(const Arabica::XPath::NodeSet& transitions); }; -- cgit v0.12