diff options
author | Stefan Radomski <github@mintwerk.de> | 2017-07-19 14:40:15 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2017-07-19 14:40:15 (GMT) |
commit | 9db80409b3ca048c4b404a43d2c224f374c0090a (patch) | |
tree | 09967edf3ce8cc89c541cdbe342fb60784f559ac /src/uscxml/interpreter | |
parent | 04b04aa6624caf73ffe4fc33f918e7f48b27da37 (diff) | |
download | uscxml-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.cpp | 230 | ||||
-rw-r--r-- | src/uscxml/interpreter/ContentExecutorImpl.h | 1 | ||||
-rw-r--r-- | src/uscxml/interpreter/FastMicroStep.cpp | 95 | ||||
-rw-r--r-- | src/uscxml/interpreter/InterpreterImpl.h | 4 |
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() { |