summaryrefslogtreecommitdiffstats
path: root/src/uscxml/interpreter
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2017-07-19 14:40:15 (GMT)
committerStefan Radomski <github@mintwerk.de>2017-07-19 14:40:15 (GMT)
commit9db80409b3ca048c4b404a43d2c224f374c0090a (patch)
tree09967edf3ce8cc89c541cdbe342fb60784f559ac /src/uscxml/interpreter
parent04b04aa6624caf73ffe4fc33f918e7f48b27da37 (diff)
downloaduscxml-9db80409b3ca048c4b404a43d2c224f374c0090a.zip
uscxml-9db80409b3ca048c4b404a43d2c224f374c0090a.tar.gz
uscxml-9db80409b3ca048c4b404a43d2c224f374c0090a.tar.bz2
DOM with Lua DataModel and dropped V8
Diffstat (limited to 'src/uscxml/interpreter')
-rw-r--r--src/uscxml/interpreter/BasicContentExecutor.cpp230
-rw-r--r--src/uscxml/interpreter/ContentExecutorImpl.h1
-rw-r--r--src/uscxml/interpreter/FastMicroStep.cpp95
-rw-r--r--src/uscxml/interpreter/InterpreterImpl.h4
4 files changed, 172 insertions, 158 deletions
diff --git a/src/uscxml/interpreter/BasicContentExecutor.cpp b/src/uscxml/interpreter/BasicContentExecutor.cpp
index 5344957..9ea2b6a 100644
--- a/src/uscxml/interpreter/BasicContentExecutor.cpp
+++ b/src/uscxml/interpreter/BasicContentExecutor.cpp
@@ -593,155 +593,89 @@ void BasicContentExecutor::processParams(std::multimap<std::string, Data>& param
paramMap.insert(make_pair(name, d));
}
}
-
+
Data BasicContentExecutor::elementAsData(XERCESC_NS::DOMElement* element, bool asExpression) {
- if (HAS_ATTR(element, kXMLCharExpr)) {
-// return _callbacks->evalAsData(ATTR(element, "expr"));
-#if 0
- if (LOCALNAME(element) == "content") {
- // test 528
- return _callbacks->evalAsData(ATTR(element, kXMLCharExpr));
- } else {
- // test 326
- return Data(ATTR(element, kXMLCharExpr), Data::INTERPRETED);
- }
-#endif
- if (asExpression) // test 453
- return Data(ATTR(element, kXMLCharExpr), Data::INTERPRETED);
- return _callbacks->evalAsData(ATTR(element, kXMLCharExpr));
- }
-
- if (HAS_ATTR(element, kXMLCharSource)) {
- // remote content from URL
-
- // test 446, test 552, test 558
- std::string src = ATTR(element, kXMLCharSource);
- URL url(ATTR(element, kXMLCharSource));
- if (!url.isAbsolute()) {
- url = URL::resolve(url, _callbacks->getBaseURL());
- }
-
- std::string content = url.getInContent();
-
- // make an attempt to parse as XML
- try {
-#if 0
- XERCESC_NS::XercesDOMParser parser;
- parser.setValidationScheme(XERCESC_NS::XercesDOMParser::Val_Never);
- parser.setDoNamespaces(true);
- parser.useScanner(XERCESC_NS::XMLUni::fgWFXMLScanner);
-
- XERCESC_NS::HandlerBase errHandler;
- parser.setErrorHandler(&errHandler);
-
- std::string tmp = url;
- XERCESC_NS::MemBufInputSource is((XMLByte*)content.c_str(), content.size(), X("fake"));
-
- parser.parse(is);
-
- Data d;
- XERCESC_NS::DOMDocument* doc = parser.adoptDocument();
- d.adoptedDoc = std::shared_ptr<XERCESC_NS::DOMDocument>(doc);
- d.node = doc->getDocumentElement();
- return d;
-#else
- std::unique_ptr<XERCESC_NS::XercesDOMParser> parser(new XERCESC_NS::XercesDOMParser());
- parser->setValidationScheme(XERCESC_NS::XercesDOMParser::Val_Always);
- parser->setDoNamespaces(true);
- parser->useScanner(XERCESC_NS::XMLUni::fgWFXMLScanner);
-
- std::unique_ptr<XERCESC_NS::ErrorHandler> errHandler(new XERCESC_NS::HandlerBase());
- parser->setErrorHandler(errHandler.get());
-
- try {
- std::string tmp = url;
- parser->parse(tmp.c_str());
-
- XERCESC_NS::DOMNode* newNode = element->getOwnerDocument()->importNode(parser->getDocument()->getDocumentElement(), true);
-
- // remove any old child elements
- while(element->getFirstElementChild() != NULL) {
- element->removeChild(element->getFirstElementChild());
- }
- // we need to save the DOM somewhere .. Data::adoptedDoc was not good enough
- element->appendChild(newNode);
-
- Data d;
-// d.adoptedDoc = std::shared_ptr<XERCESC_NS::DOMDocument>(parser->adoptDocument());
- d.node = newNode;
- return d;
- }
-
- catch (const XERCESC_NS::SAXParseException& toCatch) {
- ERROR_PLATFORM_THROW(X(toCatch.getMessage()).str());
- } catch (const XERCESC_NS::RuntimeException& toCatch) {
- ERROR_PLATFORM_THROW(X(toCatch.getMessage()).str());
- } catch (const XERCESC_NS::XMLException& toCatch) {
- ERROR_PLATFORM_THROW(X(toCatch.getMessage()).str());
- } catch (const XERCESC_NS::DOMException& toCatch) {
- ERROR_PLATFORM_THROW(X(toCatch.getMessage()).str());
- }
-
-#endif
-
- } catch (...) {
- // just ignore and return as an interpreted string below
- }
- try {
- Data d = _callbacks->getAsData(content);
- if (!d.empty())
- return d;
- } catch(...) {}
-
- return Data(spaceNormalize(content), Data::VERBATIM);
-
- } else {
- // local content in document
-
- std::list<DOMNode*> elementChildren = DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, element);
- if (elementChildren.size() > 0) {
- // always return parent element, even with a single child node
- return Data(static_cast<DOMNode*>(element));
- }
-
- std::list<DOMNode*> textChildren = DOMUtils::filterChildType(DOMNode::TEXT_NODE, element);
- if (textChildren.size() > 0) {
- std::stringstream contentSS;
- for (auto textIter = textChildren.begin(); textIter != textChildren.end(); textIter++) {
- contentSS << X((*textIter)->getNodeValue());
- }
-
- // this must be handled in getAsData
- // test294, test562
- if (LOCALNAME(element) == "content") {
- // need first try getAsData because how to pass 179 ?
- try {
- // test153, we need to throw for test150 in promela
- Data d = _callbacks->getAsData(contentSS.str());
- if (!d.empty())
- return d;
- } catch (ErrorEvent &) {
- return Data(spaceNormalize(contentSS.str()), Data::VERBATIM);
- }
- }
-
- if (asExpression) // not actually used, but likely expected
- return Data(contentSS.str(), Data::INTERPRETED);
-
- // test153, we need to throw for test150 in promela, but we need to space normalize for test558
- try {
- Data d = _callbacks->getAsData(contentSS.str());
- if (!d.empty())
- return d;
- } catch ( ... ) {}
-
- // test558
- return Data(spaceNormalize(contentSS.str()), Data::VERBATIM);
- }
- }
-
-// LOG(USCXML_WARN) << "Element " << DOMUtils::xPathForNode(element) << " did not yield any data";
- return Data();
+ // element with expr
+ if (HAS_ATTR(element, kXMLCharExpr)) {
+ std::string expr = ATTR(element, kXMLCharExpr);
+ if (_callbacks->isLegalDataValue(expr)) {
+ return Data(expr, Data::INTERPRETED);
+ } else {
+ ERROR_EXECUTION_THROW2("Expression '" + expr + "' is not a legal data value", element);
+ }
+ }
+
+ // element with external src - this ought to behave just as with child nodes below
+ if (HAS_ATTR(element, kXMLCharSource)) {
+
+ // remove any old child elements
+ while(element->getFirstElementChild() != NULL) {
+ element->removeChild(element->getFirstElementChild());
+ }
+
+ std::string src = ATTR(element, kXMLCharSource);
+ URL url(ATTR(element, kXMLCharSource));
+ if (!url.isAbsolute()) {
+ url = URL::resolve(url, _callbacks->getBaseURL());
+ }
+ std::string content = url.getInContent();
+
+ // append as XML?
+ try {
+ std::unique_ptr<XERCESC_NS::XercesDOMParser> parser(new XERCESC_NS::XercesDOMParser());
+ parser->setValidationScheme(XERCESC_NS::XercesDOMParser::Val_Always);
+ parser->setDoNamespaces(true);
+ parser->useScanner(XERCESC_NS::XMLUni::fgWFXMLScanner);
+
+ std::unique_ptr<XERCESC_NS::ErrorHandler> errHandler(new XERCESC_NS::HandlerBase());
+ parser->setErrorHandler(errHandler.get());
+
+ XERCESC_NS::MemBufInputSource is((XMLByte*)content.c_str(), content.size(), X("fake"));
+ is.setPublicId(X(url));
+
+ parser->parse(is);
+ XERCESC_NS::DOMNode* newNode = element->getOwnerDocument()->importNode(parser->getDocument()->getDocumentElement(), true);
+
+ // we need to save the DOM somewhere .. Data::adoptedDoc was not good enough
+ element->appendChild(newNode);
+ goto SOURCE_APPEND_DONE;
+ } catch (...) {
+ }
+
+ // append as text (are we leaking?)
+ XERCESC_NS::DOMText* textNode = element->getOwnerDocument()->createTextNode(X(content));
+ element->appendChild(textNode);
+ }
+SOURCE_APPEND_DONE:
+
+ if (element->hasChildNodes()) {
+ // XML elements e.g. for content with invoke
+ std::list<DOMNode*> elementChildren = DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, element);
+ if (elementChildren.size() > 0) {
+ // always return parent element, even with a single child node
+ return Data(static_cast<DOMNode*>(element));
+ }
+
+ // expression in text element
+ std::list<DOMNode*> textChildren = DOMUtils::filterChildType(DOMNode::TEXT_NODE, element);
+ if (textChildren.size() > 0) {
+ std::stringstream contentSS;
+ for (auto textIter = textChildren.begin(); textIter != textChildren.end(); textIter++) {
+ contentSS << X((*textIter)->getNodeValue());
+ }
+
+ try {
+ Data d = _callbacks->getAsData(contentSS.str());
+ if (!d.empty())
+ return d;
+ } catch(...) {}
+
+ // anything else is considered verbatim - space normalize?
+ return Data(spaceNormalize(contentSS.str()), Data::VERBATIM);
+ }
+ }
+
+ return Data();
}
}
diff --git a/src/uscxml/interpreter/ContentExecutorImpl.h b/src/uscxml/interpreter/ContentExecutorImpl.h
index c85d9a0..0c080ca 100644
--- a/src/uscxml/interpreter/ContentExecutorImpl.h
+++ b/src/uscxml/interpreter/ContentExecutorImpl.h
@@ -62,6 +62,7 @@ public:
virtual Data evalAsData(const std::string& expr) = 0;
virtual void eval(const std::string& expr) = 0;
virtual Data getAsData(const std::string& expr) = 0;
+ virtual bool isLegalDataValue(const std::string& expr) = 0;
virtual void assign(const std::string& location, const Data& data, const std::map<std::string, std::string>& attrs) = 0;
diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp
index ab6b5f9..1258279 100644
--- a/src/uscxml/interpreter/FastMicroStep.cpp
+++ b/src/uscxml/interpreter/FastMicroStep.cpp
@@ -509,6 +509,9 @@ COMPLETION_STABLISHED:
_transitions.resize(tmp.size());
_exitSets.resize(tmp.size());
+// std::list<Transition*> transSpontaneous;
+// std::list<Transition*> transEventful;
+
for (i = 0; i < _transitions.size(); i++) {
_transitions[i] = new Transition(i);
_transitions[i]->element = tmp.front();
@@ -579,7 +582,10 @@ TARGET_SET_ESTABLISHED:
if (!HAS_ATTR(_transitions[i]->element, kXMLCharEvent)) {
_transitions[i]->type |= USCXML_TRANS_SPONTANEOUS;
- }
+// transSpontaneous.push_back(_transitions[i]);
+ } else {
+// transEventful.push_back(_transitions[i]);
+ }
if (iequals(TAGNAME_CAST(_transitions[i]->element->getParentNode()), _xmlPrefix.str() + "history")) {
_transitions[i]->type |= USCXML_TRANS_HISTORY;
@@ -606,14 +612,88 @@ TARGET_SET_ESTABLISHED:
{
_exitSets[i] = getExitSet(_transitions[i]);
}
-
}
/**
* This bound by cache locality!
* Before you change anything, do benchmark!
*/
-
+
+#if 0
+#define exit1 _exitSets[t1->postFixOrder]
+#define exit2 _exitSets[t2->postFixOrder]
+
+ for (size_t set = 0; set < 2; set++) {
+ std::list<Transition*>::const_iterator transBegin;
+ std::list<Transition*>::const_iterator transEnd;
+ if (set == 0) {
+ transBegin = transEventful.begin();
+ transEnd = transEventful.end();
+ } else {
+ transBegin = transSpontaneous.begin();
+ transEnd = transSpontaneous.end();
+ }
+
+ for (auto t1Iter = transBegin; t1Iter != transEnd; t1Iter++) {
+ Transition* t1 = *t1Iter;
+ auto anc1 = _states[t1->source]->ancestors;
+ const uint32_t source1 = t1->source;
+
+ for (auto t2Iter = t1Iter; t2Iter != transEnd; t2Iter++) {
+ Transition* t2 = *t2Iter;
+
+ if (exit1.first == 0 && exit2.first == 0) {
+ goto COMPATIBLE_TRANS;
+ }
+
+ if (exit1.first <= exit2.first && exit1.second >= exit2.first) {
+ goto CONFLICTING_TRANS;
+ }
+
+ if (exit2.first <= exit1.first && exit2.second >= exit1.first) {
+ goto CONFLICTING_TRANS;
+ }
+
+ COMPATIBLE_TRANS:
+ if (t2->source == source1) {
+ goto CONFLICTING_TRANS;
+ }
+
+ if (anc1[t2->source]) {
+ goto CONFLICTING_TRANS;
+ }
+
+ if (_states[t2->source]->ancestors[source1]) {
+ goto CONFLICTING_TRANS;
+ }
+
+ t1->conflicts[t2->postFixOrder] = false;
+ // _transitions[j]->conflicts[i] = false;
+ continue;
+
+ CONFLICTING_TRANS:
+ t1->conflicts[t2->postFixOrder] = true;
+ // _transitions[j]->conflicts[i] = true;
+
+ continue;
+
+ }
+ }
+
+ for (auto t1Iter = transBegin; t1Iter != transEnd; t1Iter++) {
+ Transition* t1 = *t1Iter;
+ // conflicts matrix is symmetric
+ for (auto t2Iter = transBegin; t2Iter != t1Iter; t2Iter++) {
+ Transition* t2 = *t2Iter;
+
+ t1->conflicts[t2->postFixOrder] = t2->conflicts[t1->postFixOrder];
+ }
+ }
+
+ }
+
+
+#else
#define anc1 _states[_transitions[i]->source]->ancestors
#define exit1 _exitSets[i]
#define exit2 _exitSets[j]
@@ -659,12 +739,6 @@ CONFLICTING_TRANS:
continue;
}
-#if 0 // moved down for cache locality
- // conflicts matrix is symmetric
- for (j = 0; j < i; j++) {
- _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i];
- }
-#endif
}
for (i = 0; i < _transitions.size(); i++) {
@@ -673,7 +747,8 @@ CONFLICTING_TRANS:
_transitions[i]->conflicts[j] = _transitions[j]->conflicts[i];
}
}
-
+#endif
+
// initialize bitarrays for step()
_exitSet = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_states.size(), false);
_entrySet = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_states.size(), false);
diff --git a/src/uscxml/interpreter/InterpreterImpl.h b/src/uscxml/interpreter/InterpreterImpl.h
index 2f5fb07..1f87fd2 100644
--- a/src/uscxml/interpreter/InterpreterImpl.h
+++ b/src/uscxml/interpreter/InterpreterImpl.h
@@ -196,6 +196,10 @@ public:
return _dataModel.getAsData(expr);
}
+ virtual bool isLegalDataValue(const std::string& expr) {
+ return _dataModel.isLegalDataValue(expr);
+ }
+
virtual void assign(const std::string& location, const Data& data, const std::map<std::string, std::string>& attrs);
virtual std::string getInvokeId() {