summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/datamodel/lua
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-07-15 10:17:15 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-07-15 10:17:15 (GMT)
commit61439d49e15045bbe9c3cf55b62fc15909dd48e2 (patch)
tree6bfacf394b186226e0ba5308d8fcd735203e52a4 /src/uscxml/plugins/datamodel/lua
parentdbd110e2b7eb08c65218a5f9d09ef12fdc62c04a (diff)
downloaduscxml-61439d49e15045bbe9c3cf55b62fc15909dd48e2.zip
uscxml-61439d49e15045bbe9c3cf55b62fc15909dd48e2.tar.gz
uscxml-61439d49e15045bbe9c3cf55b62fc15909dd48e2.tar.bz2
Improved support for dot output
Diffstat (limited to 'src/uscxml/plugins/datamodel/lua')
-rw-r--r--src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp333
-rw-r--r--src/uscxml/plugins/datamodel/lua/LuaDataModel.h1
2 files changed, 301 insertions, 33 deletions
diff --git a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp
index 6fb0369..84833fb 100644
--- a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp
@@ -21,7 +21,10 @@
#include "uscxml/Common.h"
#include "LuaDataModel.h"
+
#include "LuaBridge.h"
+//#include "RefCountedPtr.h"
+
#include "uscxml/DOMUtils.h"
#include "uscxml/Message.h"
@@ -45,17 +48,6 @@ LuaDataModel::LuaDataModel() {
_luaState = NULL;
}
-static int luaEventData(lua_State * l);
-static int luaEventOrigin(lua_State * l);
-static int luaEventOriginType(lua_State * l);
-static int luaEventRaw(lua_State * l);
-static int luaEventXML(lua_State * l);
-static int luaEventName(lua_State * l);
-static int luaEventContent(lua_State * l);
-static int luaEventSendId(lua_State * l);
-static int luaEventInvokeId(lua_State * l);
-static int luaEventDestructor(lua_State * l);
-
static int luaInFunction(lua_State * l) {
luabridge::LuaRef ref = luabridge::getGlobal(l, "__interpreter");
InterpreterImpl* interpreter = ref.cast<InterpreterImpl*>();
@@ -81,9 +73,23 @@ boost::shared_ptr<DataModelImpl> LuaDataModel::create(InterpreterImpl* interpret
dm->_luaState = luaL_newstate();
luaL_openlibs(dm->_luaState);
- luabridge::getGlobalNamespace(dm->_luaState).beginClass<InterpreterImpl>("__interpreter").endClass();
+ luabridge::getGlobalNamespace(dm->_luaState).beginClass<InterpreterImpl>("Interpreter").endClass();
luabridge::getGlobalNamespace(dm->_luaState).addCFunction("In", luaInFunction);
+// luabridge::getGlobalNamespace(dm->_luaState)
+// .beginClass <uscxml::Event> ("Event")
+// .addProperty("name", &uscxml::Event::getName)
+// .addProperty("raw", &uscxml::Event::getRaw)
+// .addProperty("data", &uscxml::Event::getData)
+// .addProperty("xml", &uscxml::Event::getXML)
+// .addProperty("eventType", &uscxml::Event::getEventType)
+// .addProperty("origin", &uscxml::Event::getOrigin)
+// .addProperty("originType", &uscxml::Event::getOriginType)
+// .addProperty("content", &uscxml::Event::getContent)
+// .addProperty("invokeId", &uscxml::Event::getInvokeId)
+// .addProperty("sendId", &uscxml::Event::getSendId)
+// .endClass ();
+
luabridge::setGlobal(dm->_luaState, dm->_interpreter, "__interpreter");
return dm;
@@ -103,13 +109,161 @@ void LuaDataModel::popContext() {
void LuaDataModel::initialize() {
}
+static Data getLuaAsData(const luabridge::LuaRef& lua) {
+ Data data;
+ if (lua.isFunction()) {
+ // TODO: this might lead to a stack-overflow
+ luabridge::LuaRef luaEvald = lua();
+ return getLuaAsData(luaEvald);
+ } else if(lua.isLightUserdata() || lua.isUserdata()) {
+ // not sure what to do
+ } else if(lua.isThread()) {
+ // not sure what to do
+ } else if(lua.isNil()) {
+ data.atom = "undefined";
+ data.type = Data::INTERPRETED;
+ } else if(lua.isString()) {
+ data.atom = lua.tostring();
+ data.type = Data::VERBATIM;
+ } else if(lua.isNumber()) {
+ data.atom = lua.tostring();
+ data.type = Data::INTERPRETED;
+ } else if(lua.isTable()) {
+ for (luabridge::Iterator iter (lua); !iter.isNil (); ++iter) {
+ luabridge::LuaRef luaKey = iter.key();
+ luabridge::LuaRef luaVal = *iter;
+ data.compound[luaKey.tostring()] = getLuaAsData(luaVal);
+ }
+ }
+ return data;
+}
+
+static luabridge::LuaRef getDataAsLua(lua_State* _luaState, const Data& data) {
+ luabridge::LuaRef luaData (_luaState);
+
+ if (data.node) {
+ ERROR_EXECUTION_THROW("No DOM support in Lua datamodel");
+ }
+ if (data.compound.size() > 0) {
+ luaData = luabridge::newTable(_luaState);
+ std::map<std::string, Data>::const_iterator compoundIter = data.compound.begin();
+ while(compoundIter != data.compound.end()) {
+ luaData[compoundIter->first] = getDataAsLua(_luaState, compoundIter->second);
+ compoundIter++;
+ }
+ return luaData;
+ }
+ if (data.array.size() > 0) {
+ luaData = luabridge::newTable(_luaState);
+ std::list<Data>::const_iterator arrayIter = data.array.begin();
+ uint32_t index = 0;
+ while(arrayIter != data.array.end()) {
+ luaData[index++] = getDataAsLua(_luaState, *arrayIter);
+ arrayIter++;
+ }
+ return luaData;
+ }
+ if (data.atom.size() > 0) {
+ switch (data.type) {
+ case Data::VERBATIM: {
+ luaData = "\"" + data.atom + "\"";
+ break;
+ }
+ case Data::INTERPRETED: {
+ luaData = data.atom; // not sure
+ }
+ }
+ return luaData;
+ }
+ return luaData;
+}
+
void LuaDataModel::setEvent(const Event& event) {
+ luabridge::LuaRef luaEvent(_luaState);
+ luaEvent = luabridge::newTable(_luaState);
+
+ luaEvent["name"] = event.name;
+ luaEvent["raw"] = event.raw;
+ luaEvent["xml"] = event.xml;
+ luaEvent["origin"] = event.origin;
+ luaEvent["origintype"] = event.origintype;
+ luaEvent["content"] = event.content;
+ luaEvent["invokeId"] = event.invokeid;
+ luaEvent["sendId"] = event.sendid;
+
+ switch (event.eventType) {
+ case Event::INTERNAL:
+ luaEvent["type"] = "internal";
+ break;
+ case Event::EXTERNAL:
+ luaEvent["type"] = "external";
+ break;
+ case Event::PLATFORM:
+ luaEvent["type"] = "platform";
+ break;
+
+ default:
+ break;
+ }
+
+ if (event.dom) {
+ ERROR_EXECUTION_THROW("No DOM support in Lua datamodel");
+ } else if (event.content.length() > 0) {
+ // _event.data is a string or JSON
+ Data json = Data::fromJSON(event.content);
+ if (!json.empty()) {
+ luaEvent["data"] = getDataAsLua(_luaState, json);
+ } else {
+ luaEvent["data"] = InterpreterImpl::spaceNormalize(event.content);
+ }
+ } else {
+ // _event.data is KVP
+ Event eventCopy(event);
+
+ if (!eventCopy.params.empty()) {
+ Event::params_t::iterator paramIter = eventCopy.params.begin();
+ while(paramIter != eventCopy.params.end()) {
+ eventCopy.data.compound[paramIter->first] = paramIter->second;
+ paramIter++;
+ }
+ }
+ if (!eventCopy.namelist.empty()) {
+ Event::namelist_t::iterator nameListIter = eventCopy.namelist.begin();
+ while(nameListIter != eventCopy.namelist.end()) {
+ eventCopy.data.compound[nameListIter->first] = nameListIter->second;
+ nameListIter++;
+ }
+ }
+
+ if (!eventCopy.data.empty()) {
+ luabridge::LuaRef luaData = getDataAsLua(_luaState, eventCopy.data);
+ assert(luaEvent.isTable());
+ assert(luaData.isTable());
+ luaEvent["data"] = luaData;
+ }
+ }
+
+ luabridge::setGlobal(_luaState, luaEvent, "_event");
}
Data LuaDataModel::getStringAsData(const std::string& content) {
Data data = Data::fromJSON(content);
if (data.empty()) {
- data = Data(content, Data::VERBATIM);
+ std::string trimmedExpr = boost::trim_copy(content);
+ if (!boost::starts_with(trimmedExpr, "return")) {
+ trimmedExpr = "return(" + trimmedExpr + ");";
+ }
+
+ int preStack = lua_gettop(_luaState);
+ eval(Arabica::DOM::Element<std::string>(), trimmedExpr);
+ int postStack = lua_gettop(_luaState);
+ int retVals = postStack - preStack;
+ if (retVals == 1) {
+ data = getLuaAsData(luabridge::LuaRef::fromStack(_luaState, -1));
+ }
+ postStack = lua_gettop(_luaState);
+ lua_pop(_luaState, postStack - preStack);
+
}
return data;
}
@@ -123,6 +277,29 @@ bool LuaDataModel::isLocation(const std::string& expr) {
}
uint32_t LuaDataModel::getLength(const std::string& expr) {
+ // we need the result of the expression on the lua stack -> has to "return"!
+ std::string trimmedExpr = boost::trim_copy(expr);
+
+// luabridge::LuaRef val = luabridge::getGlobal(_luaState, expr.c_str());
+// std::cout << val.tostring() << std::endl;
+
+ if (!boost::starts_with(trimmedExpr, "return")) {
+ trimmedExpr = "return(#" + trimmedExpr + ")";
+ }
+
+ int preStack = lua_gettop(_luaState);
+ eval(Arabica::DOM::Element<std::string>(), trimmedExpr);
+ int postStack = lua_gettop(_luaState);
+ int retVals = postStack - preStack;
+
+ if (retVals == 1 && lua_isnumber(_luaState, -1)) {
+ int result = lua_tointeger(_luaState, -1);
+ lua_pop(_luaState, 1);
+ return result;
+ }
+
+ lua_pop(_luaState, retVals);
+ ERROR_EXECUTION_THROW("'" + expr + "' does not evaluate to an array.");
return 0;
}
@@ -130,35 +307,113 @@ void LuaDataModel::setForeach(const std::string& item,
const std::string& array,
const std::string& index,
uint32_t iteration) {
+ iteration++; // test153: arrays start at 1
+
+ const luabridge::LuaRef& arrRef = luabridge::getGlobal(_luaState, array.c_str());
+ if (arrRef.isTable()) {
+ int preStack = lua_gettop(_luaState);
+
+ // trigger syntax error for invalid items
+ eval(Arabica::DOM::Element<std::string>(), "return(" + item + ");");
+ int postStack = lua_gettop(_luaState);
+ lua_pop(_luaState, postStack - preStack);
+
+ const luabridge::LuaRef& val = arrRef[iteration];
+ luabridge::setGlobal(_luaState, val, item.c_str());
+
+// luabridge::LuaRef retVal = luabridge::getGlobal(_luaState, item.c_str());
+// std::cout << retVal.tostring() << std::endl;
+
+ if (index.length() > 0) {
+ // assign iteration element to index
+ luabridge::setGlobal(_luaState, iteration, index.c_str());
+ }
+ }
}
void LuaDataModel::eval(const Arabica::DOM::Element<std::string>& scriptElem,
const std::string& expr) {
-
+ int error = luaL_loadstring(_luaState, expr.c_str()) || lua_pcall(_luaState, 0, LUA_MULTRET, 0);
+ if (error) {
+ std::string errMsg = lua_tostring(_luaState, -1);
+ lua_pop(_luaState, 1); /* pop error message from the stack */
+ ERROR_EXECUTION_THROW(errMsg);
+ }
}
bool LuaDataModel::isDeclared(const std::string& expr) {
+ // see: http://lua-users.org/wiki/DetectingUndefinedVariables
return true;
}
void LuaDataModel::assign(const Arabica::DOM::Element<std::string>& assignElem,
const Arabica::DOM::Node<std::string>& node,
const std::string& content) {
+ std::string key;
+ if (HAS_ATTR(assignElem, "id")) {
+ key = ATTR(assignElem, "id");
+ } else if (HAS_ATTR(assignElem, "location")) {
+ key = ATTR(assignElem, "location");
+ }
+ 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");
+
+// lua_pushnil(_luaState);
+// lua_setglobal(_luaState, key.c_str());
+
+// luabridge::setGlobal(_luaState, luabridge::Nil(), key.c_str());
+// luabridge::LuaRef val = luabridge::getGlobal(_luaState, key.c_str());
+// std::cout << val.tostring() << std::endl;
+
+ int preStack = lua_gettop(_luaState);
+
+ if (HAS_ATTR(assignElem, "expr")) {
+ eval(Arabica::DOM::Element<std::string>(), key + " = " + ATTR(assignElem, "expr") + ";");
+ } else if (node) {
+ ERROR_EXECUTION_THROW("Cannot assign xml nodes in lua datamodel");
+ } else if (content.size() > 0) {
+ try {
+ eval(Arabica::DOM::Element<std::string>(), key + " = " + content + ";");
+ } catch (...) {
+ eval(Arabica::DOM::Element<std::string>(), key + " = " + "\"" + InterpreterImpl::spaceNormalize(content) + "\";");
+ }
+ } else {
+ eval(Arabica::DOM::Element<std::string>(), key + " = " + "nil;");
+ }
+
+// val = luabridge::getGlobal(_luaState, key.c_str());
+// std::cout << val.tostring() << std::endl;
+
+ int postStack = lua_gettop(_luaState);
+ int retVals = postStack - preStack;
}
void LuaDataModel::assign(const std::string& location, const Data& data) {
-
+ std::cout << "assign" << std::endl;
}
void LuaDataModel::init(const Arabica::DOM::Element<std::string>& dataElem,
const Arabica::DOM::Node<std::string>& node,
const std::string& content) {
-
+ assign(dataElem, node, content);
}
void LuaDataModel::init(const std::string& location, const Data& data) {
-
+ std::cout << "init" << std::endl;
}
/**
@@ -171,29 +426,43 @@ bool LuaDataModel::evalAsBool(const Arabica::DOM::Node<std::string>& node, const
// we need the result of the expression on the lua stack -> has to "return"!
std::string trimmedExpr = boost::trim_copy(expr);
if (!boost::starts_with(trimmedExpr, "return")) {
- trimmedExpr = "return(" + trimmedExpr + ")";
+ trimmedExpr = "return(" + trimmedExpr + ");";
}
- int error = luaL_loadstring(_luaState, trimmedExpr.c_str()) || lua_pcall(_luaState, 0, LUA_MULTRET, 0);
- if (error) {
- std::string errMsg = lua_tostring(_luaState, -1);
- lua_pop(_luaState, 1); /* pop error message from the stack */
- ERROR_EXECUTION_THROW(errMsg);
+
+ int preStack = lua_gettop(_luaState);
+ eval(Arabica::DOM::Element<std::string>(), trimmedExpr);
+ int postStack = lua_gettop(_luaState);
+ int retVals = postStack - preStack;
+
+ if (retVals == 1 && lua_isboolean(_luaState, -1)) {
+ bool result = lua_toboolean(_luaState, -1);
+ lua_pop(_luaState, 1);
+ return result;
}
- int stackSize = lua_gettop(_luaState);
- if (stackSize != 1)
- return false;
- if (lua_isboolean(_luaState, -1))
- return lua_toboolean(_luaState, -1);
+ lua_pop(_luaState, retVals);
return false;
}
std::string LuaDataModel::evalAsString(const std::string& expr) {
- return expr;
-}
+ std::string trimmedExpr = boost::trim_copy(expr);
+ if (!boost::starts_with(trimmedExpr, "return")) {
+ trimmedExpr = "return(" + trimmedExpr + ")";
+ }
-double LuaDataModel::evalAsNumber(const std::string& expr) {
- return 0;
+ int preStack = lua_gettop(_luaState);
+ eval(Arabica::DOM::Element<std::string>(), trimmedExpr);
+ int postStack = lua_gettop(_luaState);
+ int retVals = postStack - preStack;
+
+ if (retVals == 1 && lua_isstring(_luaState, -1)) {
+ std::string result = lua_tostring(_luaState, -1);
+ lua_pop(_luaState, 1);
+ return result;
+ }
+ lua_pop(_luaState, retVals);
+ return "";
}
+
} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/lua/LuaDataModel.h b/src/uscxml/plugins/datamodel/lua/LuaDataModel.h
index 9677307..c5d9e4b 100644
--- a/src/uscxml/plugins/datamodel/lua/LuaDataModel.h
+++ b/src/uscxml/plugins/datamodel/lua/LuaDataModel.h
@@ -84,7 +84,6 @@ public:
const std::string& expr);
virtual std::string evalAsString(const std::string& expr);
virtual bool evalAsBool(const Arabica::DOM::Node<std::string>& node, const std::string& expr);
- virtual double evalAsNumber(const std::string& expr);
protected: