summaryrefslogtreecommitdiffstats
path: root/src/uscxml/transform
diff options
context:
space:
mode:
authorStefan Radomski <sradomski@mintwerk.de>2015-12-04 08:00:18 (GMT)
committerStefan Radomski <sradomski@mintwerk.de>2015-12-04 08:00:18 (GMT)
commitb8ba0e7c31f397a66f9d509ff20a85b33619475a (patch)
tree9a5adb4f891cdc29eb80f597510e0cef8ee0a47f /src/uscxml/transform
parent57ba362eae6e8209cf560555fd4cc4bb76dbe2a1 (diff)
downloaduscxml-b8ba0e7c31f397a66f9d509ff20a85b33619475a.zip
uscxml-b8ba0e7c31f397a66f9d509ff20a85b33619475a.tar.gz
uscxml-b8ba0e7c31f397a66f9d509ff20a85b33619475a.tar.bz2
All changes up to my dissertation
Diffstat (limited to 'src/uscxml/transform')
-rw-r--r--src/uscxml/transform/ChartToFSM.cpp170
-rw-r--r--src/uscxml/transform/ChartToFSM.h4
-rw-r--r--src/uscxml/transform/ChartToPromela.cpp83
3 files changed, 221 insertions, 36 deletions
diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp
index fd7491c..d55ef24 100644
--- a/src/uscxml/transform/ChartToFSM.cpp
+++ b/src/uscxml/transform/ChartToFSM.cpp
@@ -416,6 +416,9 @@ void ChartToFSM::internalDoneSend(const Arabica::DOM::Element<std::string>& stat
if (!isState(state))
return;
+// if (LOCALNAME(state) == "scxml")
+// return;
+
// if (parentIsScxmlState(state))
// return;
@@ -596,19 +599,149 @@ void ChartToFSM::annotateRaiseAndSend(const Arabica::DOM::Element<std::string>&
}
}
-void ChartToFSM::indexTransitions() {
- indexTransitions(_scxml);
+void ChartToFSM::annotateDomain() {
+ Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true);
+ for (int i = 0; i < allTransitions.size(); i++) {
+ Element<std::string> transition(allTransitions[i]);
+ Arabica::DOM::Node<std::string> domain = getTransitionDomain(transition);
+ if (domain) {
+ transition.setAttribute("domain", (HAS_ATTR_CAST(domain, "id") ? ATTR_CAST(domain, "id") : DOMUtils::xPathForNode(domain)));
+ } else {
+ transition.setAttribute("domain", "#UNDEF");
+ }
+ }
+}
+
+void ChartToFSM::annotateExitSet() {
+ Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true);
+ for (int i = 0; i < allTransitions.size(); i++) {
+ Element<std::string> transition(allTransitions[i]);
+ Arabica::DOM::Node<std::string> domain = getTransitionDomain(transition);
+
+ Arabica::XPath::NodeSet<std::string> allStates = getAllStates();
+ std::ostringstream exitSetStr;
+ std::string seperator = "";
+ for (int j = 0; j < allStates.size(); j++) {
+ Element<std::string> state(allStates[j]);
+ if (state.getParentNode() == domain) {
+ exitSetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state));
+ seperator = ", ";
+ }
+ }
+ transition.setAttribute("exitset", exitSetStr.str());
+ }
+}
+
+void ChartToFSM::annotateEntrySet() {
+ Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true);
+ for (int i = 0; i < allTransitions.size(); i++) {
+ Element<std::string> transition(allTransitions[i]);
+
+ NodeSet<std::string> tmpTransitions;
+ NodeSet<std::string> tmpStatesToEnter;
+ NodeSet<std::string> tmpStatesForDefaultEntry;
+ std::map<std::string, Arabica::DOM::Node<std::string> > tmpDefaultHistoryContent;
+
+ tmpTransitions.push_back(transition);
+ computeEntrySet(tmpTransitions, tmpStatesToEnter, tmpStatesForDefaultEntry, tmpDefaultHistoryContent);
+
+ std::ostringstream entrySetStr;
+ std::string seperator = "";
+
+ for (int j = 0; j < tmpStatesToEnter.size(); j++) {
+ Element<std::string> state(tmpStatesToEnter[j]);
+ entrySetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state));
+ seperator = ", ";
+ }
+ for (int j = 0; j < tmpStatesForDefaultEntry.size(); j++) {
+ Element<std::string> state(tmpStatesForDefaultEntry[j]);
+ entrySetStr << seperator << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state));
+ seperator = ", ";
+ }
+ transition.setAttribute("entryset", entrySetStr.str());
- size_t index = 0;
- for (std::vector<Arabica::DOM::Element<std::string> >::iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) {
- transIter->setAttribute("priority", toStr(index));
- index++;
- }
+ }
+}
+
+void ChartToFSM::annotateConflicts() {
+ Arabica::XPath::NodeSet<std::string> allTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true);
+ Arabica::XPath::NodeSet<std::string> allStates = getAllStates();
+
+ for (int i = 0; i < allTransitions.size(); i++) {
+ Element<std::string> t1(allTransitions[i]);
+ if (!isState(Element<std::string>(t1.getParentNode())))
+ continue;
+
+ Arabica::DOM::Node<std::string> d1 = getTransitionDomain(t1);
+
+ Arabica::XPath::NodeSet<std::string> exitSet1;
+ for (int k = 0; k < allStates.size(); k++) {
+ Element<std::string> state(allStates[k]);
+ if (isDescendant(state, d1)) {
+ exitSet1.push_back(state);
+ }
+ }
+
+ std::ostringstream preemptionStr;
+ std::string seperator = "";
+
+ for (int j = 0; j < allTransitions.size(); j++) {
+ if ( i == j)
+ continue;
+
+ Element<std::string> t2(allTransitions[j]);
+ if (!isState(Element<std::string>(t2.getParentNode())))
+ continue;
+
+ Arabica::DOM::Node<std::string> d2 = getTransitionDomain(t2);
+
+ Arabica::XPath::NodeSet<std::string> exitSet2;
+ for (int k = 0; k < allStates.size(); k++) {
+ Element<std::string> state(allStates[k]);
+ if (isDescendant(state, d2)) {
+ exitSet2.push_back(state);
+ }
+ }
+
+ if (hasIntersection(exitSet1, exitSet2)) {
+ preemptionStr << seperator << (HAS_ATTR(t2, "priority") ? ATTR(t2, "priority") : DOMUtils::xPathForNode(t2));
+ seperator = ", ";
+ }
+
+// if (isDescendant(d1, d2) || isDescendant(d2, d1) || d1 == d2) {
+// preemptionStr << seperator << ATTR(t2, "priority");
+// seperator = ", ";
+// }
- // reverse indices for most prior to be in front
- std::reverse(indexedTransitions.begin(), indexedTransitions.end());
+ }
+ if (preemptionStr.str().size() > 0)
+ t1.setAttribute("conflicts", preemptionStr.str());
+
+ }
+}
+
+void ChartToFSM::indexTransitions() {
+ indexedTransitions.clear();
+ indexTransitions(_scxml);
+
+#if 1
+ size_t index = indexedTransitions.size() - 1;
+ for (std::vector<Arabica::DOM::Element<std::string> >::iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) {
+ transIter->setAttribute("priority", toStr(index));
+ index--;
+ }
+#else
+ size_t index = 0;
+ for (std::vector<Arabica::DOM::Element<std::string> >::iterator transIter = indexedTransitions.begin(); transIter != indexedTransitions.end(); transIter++) {
+ transIter->setAttribute("priority", toStr(index));
+ index++;
+ }
+#endif
+ // reverse indices for most prior to be in front
+ //std::reverse(indexedTransitions.begin(), indexedTransitions.end());
}
+#if 0
void ChartToFSM::indexTransitions(const Arabica::DOM::Element<std::string>& root) {
// breadth first traversal of transitions
Arabica::XPath::NodeSet<std::string> levelTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", root);
@@ -624,7 +757,26 @@ void ChartToFSM::indexTransitions(const Arabica::DOM::Element<std::string>& root
indexTransitions(stateElem);
}
}
+
+#else
+
+void ChartToFSM::indexTransitions(const Arabica::DOM::Element<std::string>& root) {
+ // Post-order traversal of transitions
+ Arabica::XPath::NodeSet<std::string> childStates = getChildStates(root);
+ for (int i = 0; i < childStates.size(); i++) {
+ Element<std::string> childElem(childStates[i]);
+ indexTransitions(childElem);
+ }
+
+ Arabica::XPath::NodeSet<std::string> levelTransitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", root);
+ for (int i = 0; i < levelTransitions.size(); i++) {
+ // push into index starting with least prior
+ indexedTransitions.push_back(Element<std::string>(levelTransitions[i]));
+ }
+}
+
+#endif
bool GlobalTransition::operator< (const GlobalTransition& other) const {
const std::vector<Arabica::DOM::Element<std::string> >& indexedTransitions = interpreter->indexedTransitions;
NodeSet<std::string> transitions = getTransitions();
diff --git a/src/uscxml/transform/ChartToFSM.h b/src/uscxml/transform/ChartToFSM.h
index 64d1a0c..f7e00c5 100644
--- a/src/uscxml/transform/ChartToFSM.h
+++ b/src/uscxml/transform/ChartToFSM.h
@@ -242,6 +242,10 @@ public:
virtual ~ChartToFSM();
void indexTransitions();
+ void annotateDomain();
+ void annotateExitSet();
+ void annotateEntrySet();
+ void annotateConflicts();
Arabica::DOM::Document<std::string> getDocument() const; // overwrite to return flat FSM
protected:
diff --git a/src/uscxml/transform/ChartToPromela.cpp b/src/uscxml/transform/ChartToPromela.cpp
index 867092d..965eebc 100644
--- a/src/uscxml/transform/ChartToPromela.cpp
+++ b/src/uscxml/transform/ChartToPromela.cpp
@@ -384,7 +384,7 @@ std::string PromelaCodeAnalyzer::createMacroName(const std::string& literal) {
return macroName;
}
-std::string PromelaCodeAnalyzer::getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding) {
+ std::string PromelaCodeAnalyzer::getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding) {
std::stringstream assignment;
std::map<std::string, PromelaTypedef>::const_iterator typeIter = type.types.begin();
@@ -1603,52 +1603,53 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica:
}
if (_analyzer->usesComplexEventStruct()) {
stream << padding << "{" << std::endl;
- stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), padding + " ");
- stream << padding << " tmpE.name = " << event << ";" << std::endl;
+ std::string typeReset = _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), padding + " ");
+ std::stringstream typeAssignSS;
+ typeAssignSS << padding << " tmpE.name = " << event << ";" << std::endl;
if (HAS_ATTR(nodeElem, "idlocation")) {
- stream << padding << " /* idlocation */" << std::endl;
- stream << padding << " _lastSendId = _lastSendId + 1;" << std::endl;
- stream << padding << " " << _prefix << ATTR(nodeElem, "idlocation") << " = _lastSendId;" << std::endl;
- stream << padding << " tmpE.sendid = _lastSendId;" << std::endl;
- stream << padding << " if" << std::endl;
- stream << padding << " :: _lastSendId == 2147483647 -> _lastSendId = 0;" << std::endl;
- stream << padding << " :: else -> skip;" << std::endl;
- stream << padding << " fi;" << std::endl;
+ typeAssignSS << padding << " /* idlocation */" << std::endl;
+ typeAssignSS << padding << " _lastSendId = _lastSendId + 1;" << std::endl;
+ typeAssignSS << padding << " " << _prefix << ATTR(nodeElem, "idlocation") << " = _lastSendId;" << std::endl;
+ typeAssignSS << padding << " tmpE.sendid = _lastSendId;" << std::endl;
+ typeAssignSS << padding << " if" << std::endl;
+ typeAssignSS << padding << " :: _lastSendId == 2147483647 -> _lastSendId = 0;" << std::endl;
+ typeAssignSS << padding << " :: else -> skip;" << std::endl;
+ typeAssignSS << padding << " fi;" << std::endl;
} else if (HAS_ATTR(nodeElem, "id")) {
- stream << padding << " tmpE.sendid = " << _analyzer->macroForLiteral(ATTR(nodeElem, "id")) << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.sendid = " << _analyzer->macroForLiteral(ATTR(nodeElem, "id")) << ";" << std::endl;
}
if (_invokerid.length() > 0) { // do not send invokeid if we send / raise to ourself
- stream << padding << " tmpE.invokeid = " << _analyzer->macroForLiteral(_invokerid) << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.invokeid = " << _analyzer->macroForLiteral(_invokerid) << ";" << std::endl;
}
if (_analyzer->usesEventField("origintype") && !boost::ends_with(targetQueue, "iQ")) {
- stream << padding << " tmpE.origintype = " << _analyzer->macroForLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor") << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.origintype = " << _analyzer->macroForLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor") << ";" << std::endl;
}
if (_analyzer->usesEventField("delay")) {
#if NEW_DELAY_RESHUFFLE
#else
insertOp += "!";
- stream << padding << " _lastSeqId = _lastSeqId + 1;" << std::endl;
+ typeAssignSS << padding << " _lastSeqId = _lastSeqId + 1;" << std::endl;
#endif
if (HAS_ATTR_CAST(nodeElem, "delay")) {
- stream << padding << " tmpE.delay = " << ATTR_CAST(nodeElem, "delay") << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.delay = " << ATTR_CAST(nodeElem, "delay") << ";" << std::endl;
} else if (HAS_ATTR_CAST(nodeElem, "delayexpr")) {
- stream << padding << " tmpE.delay = " << ADAPT_SRC(ATTR_CAST(nodeElem, "delayexpr")) << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.delay = " << ADAPT_SRC(ATTR_CAST(nodeElem, "delayexpr")) << ";" << std::endl;
} else {
- stream << padding << " tmpE.delay = 0;" << std::endl;
+ typeAssignSS << padding << " tmpE.delay = 0;" << std::endl;
}
#if NEW_DELAY_RESHUFFLE
#else
- stream << padding << " tmpE.seqNr = _lastSeqId;" << std::endl;
+ typeAssignSS << padding << " tmpE.seqNr = _lastSeqId;" << std::endl;
#endif
}
if (_analyzer->usesEventField("type")) {
std::string eventType = (targetQueue.compare("iQ!") == 0 ? _analyzer->macroForLiteral("internal") : _analyzer->macroForLiteral("external"));
- stream << padding << " tmpE.type = " << eventType << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.type = " << eventType << ";" << std::endl;
}
NodeSet<std::string> sendParams = filterChildElements(_nsInfo.xmlNSPrefix + "param", nodeElem);
@@ -1657,14 +1658,14 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica:
if (sendParams.size() > 0) {
for (int i = 0; i < sendParams.size(); i++) {
Element<std::string> paramElem = Element<std::string>(sendParams[i]);
- stream << padding << " tmpE.data." << ATTR(paramElem, "name") << " = " << ADAPT_SRC(ATTR(paramElem, "expr")) << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.data." << ATTR(paramElem, "name") << " = " << ADAPT_SRC(ATTR(paramElem, "expr")) << ";" << std::endl;
}
}
if (sendNameList.size() > 0) {
std::list<std::string> nameListIds = tokenizeIdRefs(sendNameList);
std::list<std::string>::iterator nameIter = nameListIds.begin();
while(nameIter != nameListIds.end()) {
- stream << padding << " tmpE.data." << *nameIter << " = " << ADAPT_SRC(*nameIter) << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.data." << *nameIter << " = " << ADAPT_SRC(*nameIter) << ";" << std::endl;
nameIter++;
}
}
@@ -1674,14 +1675,42 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica:
if (contentElem.hasChildNodes() && contentElem.getFirstChild().getNodeType() == Node_base::TEXT_NODE) {
std::string content = spaceNormalize(contentElem.getFirstChild().getNodeValue());
if (!isNumeric(content.c_str(), 10)) {
- stream << padding << " tmpE.data = " << _analyzer->macroForLiteral(content) << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.data = " << _analyzer->macroForLiteral(content) << ";" << std::endl;
} else {
- stream << padding << " tmpE.data = " << content << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.data = " << content << ";" << std::endl;
}
} else if (HAS_ATTR(contentElem, "expr")) {
- stream << padding << " tmpE.data = " << ADAPT_SRC(ATTR(contentElem, "expr")) << ";" << std::endl;
+ typeAssignSS << padding << " tmpE.data = " << ADAPT_SRC(ATTR(contentElem, "expr")) << ";" << std::endl;
}
}
+
+ // remove all fields from typeReset that are indeed set by typeAssign
+// for (std::string assigned; std::getline(typeAssignSS, assigned); ) {
+// assigned = assigned.substr(0, assigned.find('='));
+// assigned = assigned.substr(assigned.find('.'));
+// std::istringstream typeResetSS (typeReset);
+// for (std::string reset; std::getline(typeResetSS, reset); ) {
+// if (!boost::find_first(reset, assigned)) {
+// stream << reset << std::endl;
+// }
+// }
+// }
+// stream << typeAssignSS.str();
+
+ std::istringstream typeResetSS (typeReset);
+ for (std::string reset; std::getline(typeResetSS, reset); ) {
+ std::string resetField = reset.substr(0, reset.find('='));
+ resetField = resetField.substr(resetField.find('.'));
+ for (std::string assigned; std::getline(typeAssignSS, assigned); ) {
+ if (boost::find_first(resetField, assigned)) {
+ break;
+ }
+ }
+ stream << reset << std::endl;
+ }
+ stream << typeAssignSS.str();
+
+
stream << padding << " " << targetQueue << insertOp <<"tmpE;" << std::endl;
#if NEW_DELAY_RESHUFFLE
@@ -2276,7 +2305,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) {
PromelaInline::PROMELA_EVENT_ONLY);
stream << " atomic {" << std::endl;
- stream << " /* pop an event */" << std::endl;
+ stream << "/* pop an event */" << std::endl;
stream << " if" << std::endl;
stream << " :: len(" << _prefix << "iQ) != 0 -> " << _prefix << "iQ ? " << _prefix << "_event /* from internal queue */" << std::endl;
if (eventSources.size() > 0) {
@@ -2363,7 +2392,7 @@ void ChartToPromela::writeFSM(std::ostream& stream) {
stream << " fi;" << std::endl << std::endl;
- stream << " /* terminate if we are stopped */" << std::endl;
+ stream << "/* terminate if we are stopped */" << std::endl;
stream << " if" << std::endl;
stream << " :: " << _prefix << "done -> goto " << _prefix << "terminate;" << std::endl;
if (_parent != NULL) {