diff options
author | Stefan Radomski <sradomski@mintwerk.de> | 2016-02-14 14:14:28 (GMT) |
---|---|---|
committer | Stefan Radomski <sradomski@mintwerk.de> | 2016-02-14 14:14:28 (GMT) |
commit | 8e62f3801b98bf4b7f7f85b848b2fe6339c99162 (patch) | |
tree | a6c593bc3e59a864ddb69b6160e3db610fe995d6 /src | |
parent | 7b428e5435f83a7e7db37094a9197afa2dd09bf5 (diff) | |
download | uscxml-8e62f3801b98bf4b7f7f85b848b2fe6339c99162.zip uscxml-8e62f3801b98bf4b7f7f85b848b2fe6339c99162.tar.gz uscxml-8e62f3801b98bf4b7f7f85b848b2fe6339c99162.tar.bz2 |
More work on ANSI C transformation
Diffstat (limited to 'src')
-rw-r--r-- | src/uscxml/plugins/DataModel.h | 13 | ||||
-rw-r--r-- | src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp | 110 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToC.cpp | 67 |
3 files changed, 127 insertions, 63 deletions
diff --git a/src/uscxml/plugins/DataModel.h b/src/uscxml/plugins/DataModel.h index df0143d..f229a94 100644 --- a/src/uscxml/plugins/DataModel.h +++ b/src/uscxml/plugins/DataModel.h @@ -91,6 +91,19 @@ public: virtual bool isDeclared(const std::string& expr) = 0; + /** + * test147: + * <data id="Var1" expr="0"/> + * + * test150: + * <data id="Var3"> + * [1,2,3] + * </data> + * + * test277: + * <data id="Var1" expr="return"/> + * + */ virtual void assign(const Arabica::DOM::Element<std::string>& assignElem, const Arabica::DOM::Node<std::string>& node, const std::string& content) = 0; diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index fd4da3c..86bafd3 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -625,11 +625,60 @@ JSValueRef JSCDataModel::evalAsValue(const std::string& expr, bool dontThrow) { return result; } +JSValueRef JSCDataModel::getNodeAsValue(const Node<std::string>& node) { + switch (node.getNodeType()) { + case Node_base::ELEMENT_NODE: { + TO_JSC_DOMVALUE(Element); + } + case Node_base::TEXT_NODE: { + TO_JSC_DOMVALUE(Text); + } + case Node_base::CDATA_SECTION_NODE: { + TO_JSC_DOMVALUE(CDATASection); + } + case Node_base::DOCUMENT_NODE: { + TO_JSC_DOMVALUE(Document); + } + default: { + TO_JSC_DOMVALUE(Node); + } + } +} + +void JSCDataModel::assign(const std::string& location, const Data& data) { + + // flags on attribute are ignored? + if (location.compare("_sessionid") == 0) // test 322 + ERROR_EXECUTION_THROW("Cannot assign to _sessionId"); + if (location.compare("_name") == 0) + ERROR_EXECUTION_THROW("Cannot assign to _name"); + if (location.compare("_ioprocessors") == 0) // test 326 + ERROR_EXECUTION_THROW("Cannot assign to _ioprocessors"); + if (location.compare("_invokers") == 0) + ERROR_EXECUTION_THROW("Cannot assign to _invokers"); + if (location.compare("_event") == 0) + ERROR_EXECUTION_THROW("Cannot assign to _event"); + + JSValueRef exception = NULL; + if (data.node) { + JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(location.c_str()), getNodeAsValue(data.node), 0, &exception); + } else { + evalAsValue(location + " = " + Data::toJSON(data)); + } + + /** + * test157: We need to evluate, as this will not throw for 'continue' = Var[5] in + */ +// JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(location.c_str()), getDataAsValue(data), 0, &exception); + + if (exception) + handleException(exception); +} + void JSCDataModel::assign(const Element<std::string>& assignElem, const Node<std::string>& node, const std::string& content) { std::string key; - JSValueRef exception = NULL; if (HAS_ATTR(assignElem, "id")) { key = ATTR(assignElem, "id"); } else if (HAS_ATTR(assignElem, "location")) { @@ -638,63 +687,30 @@ void JSCDataModel::assign(const Element<std::string>& assignElem, if (key.length() == 0) { ERROR_EXECUTION_THROW("Assign element has neither id nor location"); } - // flags on attribute are ignored? - if (key.compare("_sessionid") == 0) // test 322 - ERROR_EXECUTION_THROW("Cannot assign to _sessionId"); - if (key.compare("_name") == 0) - ERROR_EXECUTION_THROW("Cannot assign to _name"); - if (key.compare("_ioprocessors") == 0) // test 326 - ERROR_EXECUTION_THROW("Cannot assign to _ioprocessors"); - if (key.compare("_invokers") == 0) - ERROR_EXECUTION_THROW("Cannot assign to _invokers"); - if (key.compare("_event") == 0) - ERROR_EXECUTION_THROW("Cannot assign to _event"); if (HAS_ATTR(assignElem, "expr")) { - evalAsValue(key + " = " + ATTR(assignElem, "expr")); + assign(key, Data(ATTR(assignElem, "expr"), Data::INTERPRETED)); } else if (node) { - JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(key.c_str()), getNodeAsValue(node), 0, &exception); - if (exception) - handleException(exception); + Data d; + d.node = node; + assign(key, d); } else if (content.size() > 0) { try { - evalAsValue(key + " = " + content); - } catch (...) { - evalAsValue(key + " = " + "\"" + InterpreterImpl::spaceNormalize(content) + "\""); + Data d = Data::fromJSON(content); + if (d.empty()) + throw Event(); + assign(key, Data(d, Data::INTERPRETED)); + } catch (Event e) { + assign(key, Data("\"" + InterpreterImpl::spaceNormalize(content) + "\"", Data::INTERPRETED)); } } else { + JSValueRef exception = NULL; JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(key.c_str()), JSValueMakeUndefined(_ctx), 0, &exception); if (exception) handleException(exception); } } -JSValueRef JSCDataModel::getNodeAsValue(const Node<std::string>& node) { - switch (node.getNodeType()) { - case Node_base::ELEMENT_NODE: { - TO_JSC_DOMVALUE(Element); - } - case Node_base::TEXT_NODE: { - TO_JSC_DOMVALUE(Text); - } - case Node_base::CDATA_SECTION_NODE: { - TO_JSC_DOMVALUE(CDATASection); - } - case Node_base::DOCUMENT_NODE: { - TO_JSC_DOMVALUE(Document); - } - default: { - TO_JSC_DOMVALUE(Node); - } - } -} - -void JSCDataModel::assign(const std::string& location, const Data& data) { - std::stringstream ssJSON; - ssJSON << data; - evalAsValue(location + " = " + ssJSON.str()); -} - void JSCDataModel::init(const Element<std::string>& dataElem, const Node<std::string>& node, const std::string& content) { @@ -708,7 +724,9 @@ void JSCDataModel::init(const Element<std::string>& dataElem, } else if (HAS_ATTR(dataElem, "location")) { key = ATTR(dataElem, "location"); } - evalAsValue(key + " = undefined", true); + if (key.size() > 0) { + evalAsValue(key + " = undefined", true); + } throw e; } } diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp index c6be393..7cc50fc 100644 --- a/src/uscxml/transform/ChartToC.cpp +++ b/src/uscxml/transform/ChartToC.cpp @@ -690,13 +690,15 @@ void ChartToC::writeTypes(std::ostream& stream) { stream << "typedef struct uscxml_elem_send uscxml_elem_send;" << std::endl; stream << "typedef struct uscxml_elem_param uscxml_elem_param;" << std::endl; stream << "typedef struct uscxml_elem_data uscxml_elem_data;" << std::endl; + stream << "typedef struct uscxml_elem_assign uscxml_elem_assign;" << std::endl; stream << "typedef struct uscxml_elem_donedata uscxml_elem_donedata;" << std::endl; stream << "typedef struct uscxml_elem_foreach uscxml_elem_foreach;" << std::endl; stream << std::endl; stream << "typedef void* (*dequeue_internal_t)(const uscxml_ctx* ctx);" << std::endl; stream << "typedef void* (*dequeue_external_t)(const uscxml_ctx* ctx);" << std::endl; - stream << "typedef int (*is_enabled_t)(const uscxml_ctx* ctx, const uscxml_transition* transition, const void* event);" << std::endl; + stream << "typedef int (*is_enabled_t)(const uscxml_ctx* ctx, const uscxml_transition* transition);" << std::endl; + stream << "typedef int (*is_matched_t)(const uscxml_ctx* ctx, const uscxml_transition* transition, const void* event);" << std::endl; stream << "typedef int (*is_true_t)(const uscxml_ctx* ctx, const char* expr);" << std::endl; stream << "typedef int (*exec_content_t)(const uscxml_ctx* ctx, const uscxml_state* state, const void* event);" << std::endl; stream << "typedef int (*raise_done_event_t)(const uscxml_ctx* ctx, const uscxml_state* state, const uscxml_elem_donedata* donedata);" << std::endl; @@ -709,7 +711,7 @@ void ChartToC::writeTypes(std::ostream& stream) { stream << "typedef int (*exec_content_foreach_init_t)(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach);" << std::endl; stream << "typedef int (*exec_content_foreach_next_t)(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach);" << std::endl; stream << "typedef int (*exec_content_foreach_done_t)(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach);" << std::endl; - stream << "typedef int (*exec_content_assign_t)(const uscxml_ctx* ctx, const char* location, const char* expr);" << std::endl; + stream << "typedef int (*exec_content_assign_t)(const uscxml_ctx* ctx, const uscxml_elem_assign* assign);" << std::endl; stream << "typedef int (*exec_content_init_t)(const uscxml_ctx* ctx, const uscxml_elem_data* data);" << std::endl; stream << "typedef int (*exec_content_cancel_t)(const uscxml_ctx* ctx, const char* sendid, const char* sendidexpr);" << std::endl; stream << "typedef int (*exec_content_finalize_t)(const uscxml_ctx* ctx, const uscxml_elem_invoke* invoker, const void* event);" << std::endl; @@ -748,6 +750,16 @@ void ChartToC::writeTypes(std::ostream& stream) { stream << std::endl; stream << "/**" << std::endl; + stream << " * All information pertaining to an <assign> element." << std::endl; + stream << " */" << std::endl; + stream << "struct uscxml_elem_assign {" << std::endl; + stream << " const char* location;" << std::endl; + stream << " const char* expr;" << std::endl; + stream << " const char* content;" << std::endl; + stream << "};" << std::endl; + stream << std::endl; + + stream << "/**" << std::endl; stream << " * All information pertaining to any state element." << std::endl; stream << " */" << std::endl; stream << "struct uscxml_state {" << std::endl; @@ -872,6 +884,7 @@ void ChartToC::writeTypes(std::ostream& stream) { stream << " dequeue_internal_t dequeue_internal;" << std::endl; stream << " dequeue_external_t dequeue_external;" << std::endl; stream << " is_enabled_t is_enabled;" << std::endl; + stream << " is_matched_t is_matched;" << std::endl; stream << " is_true_t is_true;" << std::endl; stream << " raise_done_event_t raise_done_event;" << std::endl; stream << std::endl; @@ -1264,20 +1277,7 @@ void ChartToC::writeExecContent(std::ostream& stream, const Arabica::DOM::Node<s stream << padding; stream << "if likely(ctx->exec_content_assign != NULL) {" << std::endl; stream << padding; - stream << " if ((ctx->exec_content_assign(ctx, "; - stream << (HAS_ATTR(elem, "location") ? "\"" + escape(ATTR(elem, "location")) + "\"" : "NULL") << ", "; - if (HAS_ATTR(elem, "expr")) { - stream << "\"" + escape(ATTR(elem, "expr")) + "\""; - } else { - NodeSet<std::string> assignTexts = filterChildType(Node_base::TEXT_NODE, elem); - if (assignTexts.size() > 0) { - stream << "\""; - writeExecContent(stream, assignTexts[0], 0); - stream << "\""; - } else { - stream << "NULL"; - } - } + stream << " if ((ctx->exec_content_assign(ctx, &" << _prefix << "_elem_assigns[" << ATTR(elem, "documentOrder") << "]"; stream << ")) != USCXML_ERR_OK) return err;" << std::endl; stream << padding << "} else {" << std::endl; stream << padding << " return USCXML_ERR_MISSING_CALLBACK;" << std::endl; @@ -1485,6 +1485,38 @@ void ChartToC::writeElementInfo(std::ostream& stream) { stream << std::endl; } + NodeSet<std::string> assigns = DOMUtils::inDocumentOrder(_nsInfo.xmlNSPrefix + "assign", _scxml); + if (assigns.size() > 0) { + _hasElement.insert("assign"); + stream << "static const uscxml_elem_assign " << _prefix << "_elem_assigns[" << assigns.size() << "] = {" << std::endl; + stream << " /* location, expr, content */" << std::endl; + + for (size_t i = 0; i < assigns.size(); i++) { + Element<std::string> assign(assigns[i]); + + stream << " { "; + stream << (HAS_ATTR(assign, "location") ? "\"" + escape(ATTR(assign, "location")) + "\"" : "NULL") << ", "; + stream << (HAS_ATTR(assign, "expr") ? "\"" + escape(ATTR(assign, "expr")) + "\"" : "NULL") << ", "; + + NodeSet<std::string> assignTexts = filterChildType(Node_base::TEXT_NODE, assign); + if (assignTexts.size() > 0) { + if (boost::trim_copy(assignTexts[0].getNodeValue()).length() > 0) { + std::string escaped = escape(assignTexts[0].getNodeValue()); + stream << "\"" << escaped << "\""; + } + } else { + stream << "NULL"; + } + stream << " }," << std::endl; + + assign.setAttribute("documentOrder", toStr(i)); + } + + stream << "};" << std::endl; + stream << std::endl; + + } + NodeSet<std::string> datas = DOMUtils::inDocumentOrder(_nsInfo.xmlNSPrefix + "data", _scxml); if (datas.size() > 0) { _hasElement.insert("data"); @@ -2169,7 +2201,8 @@ void ChartToC::writeFSM(std::ostream& stream) { stream << " if ((USCXML_GET_TRANS(i).event == NULL && ctx->event == NULL) || " << std::endl; stream << " (USCXML_GET_TRANS(i).event != NULL && ctx->event != NULL)) {" << std::endl; stream << " /* is it enabled? */" << std::endl; - stream << " if (ctx->is_enabled(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) {" << std::endl; + stream << " if ((ctx->event == NULL || ctx->is_matched(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) &&" << std::endl; + stream << " (USCXML_GET_TRANS(i).condition == NULL || ctx->is_enabled(ctx, &USCXML_GET_TRANS(i)) > 0)) {" << std::endl; stream << " /* remember that we found a transition */" << std::endl; stream << " ctx->flags |= USCXML_CTX_TRANSITION_FOUND;" << std::endl; stream << std::endl; |