summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-07-08 00:20:56 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-07-08 00:20:56 (GMT)
commitdbd110e2b7eb08c65218a5f9d09ef12fdc62c04a (patch)
tree93444e4c106eeca34d928521bedbda8080410795
parentd5e1f6397c52513018cd59972cf5ca8740de18eb (diff)
downloaduscxml-dbd110e2b7eb08c65218a5f9d09ef12fdc62c04a.zip
uscxml-dbd110e2b7eb08c65218a5f9d09ef12fdc62c04a.tar.gz
uscxml-dbd110e2b7eb08c65218a5f9d09ef12fdc62c04a.tar.bz2
First signs of Lua Datamodel
-rw-r--r--CMakeLists.txt13
-rw-r--r--config.h.in2
-rw-r--r--contrib/src/LuaBridge/LuaBridge.h142
-rw-r--r--contrib/src/LuaBridge/RefCountedObject.h363
-rw-r--r--contrib/src/LuaBridge/RefCountedPtr.h251
-rw-r--r--contrib/src/LuaBridge/detail/CFunctions.h442
-rw-r--r--contrib/src/LuaBridge/detail/ClassInfo.h73
-rw-r--r--contrib/src/LuaBridge/detail/Constructor.h204
-rw-r--r--contrib/src/LuaBridge/detail/FuncTraits.h852
-rw-r--r--contrib/src/LuaBridge/detail/Iterator.h114
-rw-r--r--contrib/src/LuaBridge/detail/LuaException.h113
-rw-r--r--contrib/src/LuaBridge/detail/LuaHelpers.h143
-rw-r--r--contrib/src/LuaBridge/detail/LuaRef.h1215
-rw-r--r--contrib/src/LuaBridge/detail/Namespace.h1136
-rw-r--r--contrib/src/LuaBridge/detail/Stack.h469
-rw-r--r--contrib/src/LuaBridge/detail/TypeList.h174
-rw-r--r--contrib/src/LuaBridge/detail/TypeTraits.h125
-rw-r--r--contrib/src/LuaBridge/detail/Userdata.h817
-rw-r--r--contrib/src/LuaBridge/detail/dump.h28
-rw-r--r--embedding/csharp/uSCXMLEmbedding.suobin40448 -> 38912 bytes
-rw-r--r--src/uscxml/Factory.cpp11
-rw-r--r--src/uscxml/Interpreter.cpp4
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp6
-rw-r--r--src/uscxml/plugins/datamodel/CMakeLists.txt24
-rw-r--r--src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp199
-rw-r--r--src/uscxml/plugins/datamodel/lua/LuaDataModel.h111
-rw-r--r--test/uscxml/test-lua.scxml6
-rw-r--r--test/w3c/lua/test144.scxml19
-rw-r--r--test/w3c/lua/test147.scxml27
-rw-r--r--test/w3c/lua/test148.scxml28
-rw-r--r--test/w3c/lua/test149.scxml23
-rw-r--r--test/w3c/lua/test150.scxml35
-rw-r--r--test/w3c/lua/test151.scxml35
-rw-r--r--test/w3c/lua/test152.scxml41
-rw-r--r--test/w3c/lua/test153.scxml32
-rw-r--r--test/w3c/lua/test155.scxml21
-rw-r--r--test/w3c/lua/test156.scxml23
-rw-r--r--test/w3c/lua/test158.scxml21
-rw-r--r--test/w3c/lua/test159.scxml18
-rw-r--r--test/w3c/lua/test172.scxml17
-rw-r--r--test/w3c/lua/test173.scxml18
-rw-r--r--test/w3c/lua/test174.scxml18
-rw-r--r--test/w3c/lua/test175.scxml24
-rw-r--r--test/w3c/lua/test176.scxml27
-rw-r--r--test/w3c/lua/test178.scxml23
-rw-r--r--test/w3c/lua/test179.scxml15
-rw-r--r--test/w3c/lua/test183.scxml17
-rw-r--r--test/w3c/lua/test185.scxml19
-rw-r--r--test/w3c/lua/test186.scxml28
-rw-r--r--test/w3c/lua/test187.scxml30
-rw-r--r--test/w3c/lua/test189.scxml19
-rw-r--r--test/w3c/lua/test190.scxml32
-rw-r--r--test/w3c/lua/test191.scxml29
-rw-r--r--test/w3c/lua/test192.scxml44
-rw-r--r--test/w3c/lua/test193.scxml21
-rw-r--r--test/w3c/lua/test194.scxml18
-rw-r--r--test/w3c/lua/test198.scxml15
-rw-r--r--test/w3c/lua/test199.scxml14
-rw-r--r--test/w3c/lua/test200.scxml14
-rw-r--r--test/w3c/lua/test201.scxml15
-rw-r--r--test/w3c/lua/test205.scxml26
-rw-r--r--test/w3c/lua/test207.scxml47
-rw-r--r--test/w3c/lua/test208.scxml16
-rw-r--r--test/w3c/lua/test210.scxml20
-rw-r--r--test/w3c/lua/test215.scxml27
-rw-r--r--test/w3c/lua/test216.scxml20
-rw-r--r--test/w3c/lua/test216sub1.scxml5
-rw-r--r--test/w3c/lua/test220.scxml21
-rw-r--r--test/w3c/lua/test223.scxml27
-rw-r--r--test/w3c/lua/test224.scxml28
-rw-r--r--test/w3c/lua/test225.scxml34
-rw-r--r--test/w3c/lua/test226.scxml18
-rw-r--r--test/w3c/lua/test226sub1.scxml14
-rw-r--r--test/w3c/lua/test228.scxml29
-rw-r--r--test/w3c/lua/test229.scxml38
-rw-r--r--test/w3c/lua/test230.scxml56
-rw-r--r--test/w3c/lua/test232.scxml33
-rw-r--r--test/w3c/lua/test233.scxml34
-rw-r--r--test/w3c/lua/test234.scxml61
-rw-r--r--test/w3c/lua/test235.scxml21
-rw-r--r--test/w3c/lua/test236.scxml35
-rw-r--r--test/w3c/lua/test237.scxml37
-rw-r--r--test/w3c/lua/test239.scxml27
-rw-r--r--test/w3c/lua/test239sub1.scxml5
-rw-r--r--test/w3c/lua/test240.scxml63
-rw-r--r--test/w3c/lua/test241.scxml88
-rw-r--r--test/w3c/lua/test242.scxml48
-rw-r--r--test/w3c/lua/test242sub1.scxml5
-rw-r--r--test/w3c/lua/test243.scxml33
-rw-r--r--test/w3c/lua/test244.scxml37
-rw-r--r--test/w3c/lua/test245.scxml32
-rw-r--r--test/w3c/lua/test247.scxml20
-rw-r--r--test/w3c/lua/test250.scxml39
-rw-r--r--test/w3c/lua/test252.scxml40
-rw-r--r--test/w3c/lua/test253.scxml67
-rw-r--r--test/w3c/lua/test276.scxml14
-rw-r--r--test/w3c/lua/test276sub1.scxml16
-rw-r--r--test/w3c/lua/test277.scxml24
-rw-r--r--test/w3c/lua/test278.scxml15
-rw-r--r--test/w3c/lua/test279.scxml16
-rw-r--r--test/w3c/lua/test280.scxml25
-rw-r--r--test/w3c/lua/test286.scxml15
-rw-r--r--test/w3c/lua/test287.scxml16
-rw-r--r--test/w3c/lua/test294.scxml38
-rw-r--r--test/w3c/lua/test298.scxml24
-rw-r--r--test/w3c/lua/test301.scxml11
-rw-r--r--test/w3c/lua/test302.scxml13
-rw-r--r--test/w3c/lua/test303.scxml18
-rw-r--r--test/w3c/lua/test304.scxml11
-rw-r--r--test/w3c/lua/test307.scxml35
-rw-r--r--test/w3c/lua/test309.scxml10
-rw-r--r--test/w3c/lua/test310.scxml13
-rw-r--r--test/w3c/lua/test311.scxml14
-rw-r--r--test/w3c/lua/test312.scxml17
-rw-r--r--test/w3c/lua/test313.scxml18
-rw-r--r--test/w3c/lua/test314.scxml27
-rw-r--r--test/w3c/lua/test318.scxml24
-rw-r--r--test/w3c/lua/test319.scxml17
-rw-r--r--test/w3c/lua/test321.scxml13
-rw-r--r--test/w3c/lua/test322.scxml26
-rw-r--r--test/w3c/lua/test323.scxml13
-rw-r--r--test/w3c/lua/test324.scxml17
-rw-r--r--test/w3c/lua/test325.scxml15
-rw-r--r--test/w3c/lua/test326.scxml29
-rw-r--r--test/w3c/lua/test329.scxml46
-rw-r--r--test/w3c/lua/test330.scxml20
-rw-r--r--test/w3c/lua/test331.scxml51
-rw-r--r--test/w3c/lua/test332.scxml26
-rw-r--r--test/w3c/lua/test333.scxml13
-rw-r--r--test/w3c/lua/test335.scxml13
-rw-r--r--test/w3c/lua/test336.scxml23
-rw-r--r--test/w3c/lua/test337.scxml13
-rw-r--r--test/w3c/lua/test338.scxml35
-rw-r--r--test/w3c/lua/test339.scxml13
-rw-r--r--test/w3c/lua/test342.scxml23
-rw-r--r--test/w3c/lua/test343.scxml27
-rw-r--r--test/w3c/lua/test344.scxml20
-rw-r--r--test/w3c/lua/test346.scxml46
-rw-r--r--test/w3c/lua/test347.scxml36
-rw-r--r--test/w3c/lua/test348.scxml13
-rw-r--r--test/w3c/lua/test349.scxml25
-rw-r--r--test/w3c/lua/test350.scxml20
-rw-r--r--test/w3c/lua/test351.scxml39
-rw-r--r--test/w3c/lua/test352.scxml24
-rw-r--r--test/w3c/lua/test354.scxml44
-rw-r--r--test/w3c/lua/test355.scxml12
-rw-r--r--test/w3c/lua/test364.scxml71
-rw-r--r--test/w3c/lua/test372.scxml25
-rw-r--r--test/w3c/lua/test375.scxml20
-rw-r--r--test/w3c/lua/test376.scxml20
-rw-r--r--test/w3c/lua/test377.scxml23
-rw-r--r--test/w3c/lua/test378.scxml23
-rw-r--r--test/w3c/lua/test387.scxml85
-rw-r--r--test/w3c/lua/test388.scxml66
-rw-r--r--test/w3c/lua/test396.scxml13
-rw-r--r--test/w3c/lua/test399.scxml57
-rw-r--r--test/w3c/lua/test401.scxml17
-rw-r--r--test/w3c/lua/test402.scxml34
-rw-r--r--test/w3c/lua/test403a.scxml38
-rw-r--r--test/w3c/lua/test403b.scxml32
-rw-r--r--test/w3c/lua/test403c.scxml45
-rw-r--r--test/w3c/lua/test404.scxml48
-rw-r--r--test/w3c/lua/test405.scxml58
-rw-r--r--test/w3c/lua/test406.scxml52
-rw-r--r--test/w3c/lua/test407.scxml19
-rw-r--r--test/w3c/lua/test409.scxml28
-rw-r--r--test/w3c/lua/test411.scxml28
-rw-r--r--test/w3c/lua/test412.scxml44
-rw-r--r--test/w3c/lua/test413.scxml36
-rw-r--r--test/w3c/lua/test415.scxml13
-rw-r--r--test/w3c/lua/test416.scxml19
-rw-r--r--test/w3c/lua/test417.scxml28
-rw-r--r--test/w3c/lua/test419.scxml14
-rw-r--r--test/w3c/lua/test421.scxml23
-rw-r--r--test/w3c/lua/test422.scxml73
-rw-r--r--test/w3c/lua/test423.scxml21
-rw-r--r--test/w3c/lua/test436.scxml15
-rw-r--r--test/w3c/lua/test444.scxml14
-rw-r--r--test/w3c/lua/test445.scxml13
-rw-r--r--test/w3c/lua/test446.scxml19
-rw-r--r--test/w3c/lua/test446.txt1
-rw-r--r--test/w3c/lua/test448.scxml30
-rw-r--r--test/w3c/lua/test449.scxml10
-rw-r--r--test/w3c/lua/test451.scxml13
-rw-r--r--test/w3c/lua/test452.scxml25
-rw-r--r--test/w3c/lua/test453.scxml19
-rw-r--r--test/w3c/lua/test456.scxml19
-rw-r--r--test/w3c/lua/test457.scxml61
-rw-r--r--test/w3c/lua/test459.scxml43
-rw-r--r--test/w3c/lua/test460.scxml30
-rw-r--r--test/w3c/lua/test463.scxml14
-rw-r--r--test/w3c/lua/test464.scxml13
-rw-r--r--test/w3c/lua/test465.scxml19
-rw-r--r--test/w3c/lua/test466.scxml13
-rw-r--r--test/w3c/lua/test467.scxml10
-rw-r--r--test/w3c/lua/test468.scxml22
-rw-r--r--test/w3c/lua/test469.scxml23
-rw-r--r--test/w3c/lua/test470.scxml22
-rw-r--r--test/w3c/lua/test473.scxml36
-rw-r--r--test/w3c/lua/test474.scxml35
-rw-r--r--test/w3c/lua/test475.scxml35
-rw-r--r--test/w3c/lua/test476.scxml35
-rw-r--r--test/w3c/lua/test477.scxml35
-rw-r--r--test/w3c/lua/test478.scxml34
-rw-r--r--test/w3c/lua/test479.scxml34
-rw-r--r--test/w3c/lua/test480.scxml30
-rw-r--r--test/w3c/lua/test481.scxml35
-rw-r--r--test/w3c/lua/test482.scxml14
-rw-r--r--test/w3c/lua/test483.scxml25
-rw-r--r--test/w3c/lua/test487.scxml16
-rw-r--r--test/w3c/lua/test488.scxml27
-rw-r--r--test/w3c/lua/test495.scxml20
-rw-r--r--test/w3c/lua/test496.scxml13
-rw-r--r--test/w3c/lua/test500.scxml13
-rw-r--r--test/w3c/lua/test501.scxml17
-rw-r--r--test/w3c/lua/test503.scxml35
-rw-r--r--test/w3c/lua/test504.scxml71
-rw-r--r--test/w3c/lua/test505.scxml44
-rw-r--r--test/w3c/lua/test506.scxml48
-rw-r--r--test/w3c/lua/test509.scxml16
-rw-r--r--test/w3c/lua/test510.scxml21
-rw-r--r--test/w3c/lua/test513.txt16
-rw-r--r--test/w3c/lua/test518.scxml17
-rw-r--r--test/w3c/lua/test519.scxml17
-rw-r--r--test/w3c/lua/test520.scxml19
-rw-r--r--test/w3c/lua/test521.scxml19
-rw-r--r--test/w3c/lua/test522.scxml19
-rw-r--r--test/w3c/lua/test525.scxml22
-rw-r--r--test/w3c/lua/test527.scxml20
-rw-r--r--test/w3c/lua/test528.scxml25
-rw-r--r--test/w3c/lua/test529.scxml20
-rw-r--r--test/w3c/lua/test530.scxml26
-rw-r--r--test/w3c/lua/test531.scxml18
-rw-r--r--test/w3c/lua/test532.scxml18
-rw-r--r--test/w3c/lua/test533.scxml59
-rw-r--r--test/w3c/lua/test534.scxml16
-rw-r--r--test/w3c/lua/test537.scxml14
-rw-r--r--test/w3c/lua/test539.scxml24
-rw-r--r--test/w3c/lua/test539.txt4
-rw-r--r--test/w3c/lua/test540.scxml20
-rw-r--r--test/w3c/lua/test540.txt3
-rw-r--r--test/w3c/lua/test542.scxml32
-rw-r--r--test/w3c/lua/test543.scxml16
-rw-r--r--test/w3c/lua/test544.scxml15
-rw-r--r--test/w3c/lua/test545.scxml19
-rw-r--r--test/w3c/lua/test546.scxml15
-rw-r--r--test/w3c/lua/test547.scxml31
-rw-r--r--test/w3c/lua/test550.scxml15
-rw-r--r--test/w3c/lua/test551.scxml15
-rw-r--r--test/w3c/lua/test552.scxml14
-rw-r--r--test/w3c/lua/test552.txt1
-rw-r--r--test/w3c/lua/test553.scxml19
-rw-r--r--test/w3c/lua/test554.scxml23
-rw-r--r--test/w3c/lua/test555.scxml24
-rw-r--r--test/w3c/lua/test557.scxml24
-rw-r--r--test/w3c/lua/test557.txt4
-rw-r--r--test/w3c/lua/test558.scxml22
-rw-r--r--test/w3c/lua/test558.txt3
-rw-r--r--test/w3c/lua/test560.scxml16
-rw-r--r--test/w3c/lua/test561.scxml21
-rw-r--r--test/w3c/lua/test562.scxml19
-rw-r--r--test/w3c/lua/test567.scxml29
-rw-r--r--test/w3c/lua/test568.scxml12
-rw-r--r--test/w3c/lua/test569.scxml12
-rw-r--r--test/w3c/lua/test570.scxml40
-rw-r--r--test/w3c/lua/test576.scxml35
-rw-r--r--test/w3c/lua/test577.scxml17
-rw-r--r--test/w3c/lua/test578.scxml16
-rw-r--r--test/w3c/lua/test579.scxml52
-rw-r--r--test/w3c/lua/test580.scxml37
270 files changed, 13293 insertions, 5 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9fae0c8..f016f98 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -315,6 +315,7 @@ OPTION(BUILD_DM_ECMA "Build with ECMAScript datamodel" ON)
OPTION(BUILD_DM_XPATH "Build with XPath datamodel" ON)
OPTION(BUILD_DM_PROLOG "Build with Prolog datamodel" ON)
OPTION(BUILD_DM_PROMELA "Build with Promela datamodel" ON)
+OPTION(BUILD_DM_LUA "Build with Lua datamodel" ON)
# a dummy target to depend on the targets needed for tests, see:
# http://stackoverflow.com/questions/733475/cmake-ctest-make-test-doesnt-build-tests
@@ -686,6 +687,16 @@ else()
endif()
+set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SHARED})
+find_package(Lua)
+if (LUA_FOUND)
+ include_directories (${LUA_INCLUDE_DIR})
+ include_directories(${PROJECT_SOURCE_DIR}/contrib/src/LuaBridge)
+ list (APPEND USCXML_OPT_LIBS ${LUA_LIBRARIES})
+endif()
+set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_ORIG})
+
+
find_package(OpenSSL)
if (OPENSSL_FOUND)
set(OPENSSL_HAS_ELIPTIC_CURVES OFF)
@@ -932,6 +943,8 @@ foreach( FILE ${USCXML_FILES} )
source_group("Datamodel\\Promela" FILES ${FILE})
elseif (${PATH} MATCHES ".*datamodel\\/xpath.*")
source_group("Datamodel\\XPath" FILES ${FILE})
+ elseif (${PATH} MATCHES ".*datamodel\\/lua.*")
+ source_group("Datamodel\\Lua" FILES ${FILE})
elseif (${PATH} MATCHES ".*datamodel\\/null.*")
source_group("Datamodel\\NULL" FILES ${FILE})
diff --git a/config.h.in b/config.h.in
index a6b8c74..814760e 100644
--- a/config.h.in
+++ b/config.h.in
@@ -51,6 +51,7 @@
#cmakedefine BUILD_DM_PROMELA
#cmakedefine BUILD_DM_ECMA
#cmakedefine BUILD_DM_XPATH
+#cmakedefine BUILD_DM_LUA
/** Optional libraries we found */
#cmakedefine UMUNDO_FOUND
@@ -63,6 +64,7 @@
#cmakedefine LIBICAL_FOUND
#cmakedefine SWI_FOUND
#cmakedefine FFMPEG_FOUND
+#cmakedefine LUA_FOUND
#cmakedefine OPENSCENEGRAPH_FOUND
#cmakedefine PROTOBUF_FOUND
#cmakedefine CORELOCATION_FOUND
diff --git a/contrib/src/LuaBridge/LuaBridge.h b/contrib/src/LuaBridge/LuaBridge.h
new file mode 100644
index 0000000..1928e9a
--- /dev/null
+++ b/contrib/src/LuaBridge/LuaBridge.h
@@ -0,0 +1,142 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef LUABRIDGE_LUABRIDGE_HEADER
+#define LUABRIDGE_LUABRIDGE_HEADER
+
+// All #include dependencies are listed here
+// instead of in the individual header files.
+//
+#include <cassert>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <typeinfo>
+
+#define LUABRIDGE_MAJOR_VERSION 2
+#define LUABRIDGE_MINOR_VERSION 0
+#define LUABRIDGE_VERSION 200
+
+namespace luabridge
+{
+
+// Forward declaration
+//
+template <class T>
+struct Stack;
+
+#include "detail/LuaHelpers.h"
+
+#include "detail/TypeTraits.h"
+#include "detail/TypeList.h"
+#include "detail/FuncTraits.h"
+#include "detail/Constructor.h"
+#include "detail/Stack.h"
+#include "detail/ClassInfo.h"
+
+class LuaRef;
+
+#include "detail/LuaException.h"
+#include "detail/LuaRef.h"
+#include "detail/Iterator.h"
+
+//------------------------------------------------------------------------------
+/**
+ security options.
+*/
+class Security
+{
+public:
+ static bool hideMetatables ()
+ {
+ return getSettings().hideMetatables;
+ }
+
+ static void setHideMetatables (bool shouldHide)
+ {
+ getSettings().hideMetatables = shouldHide;
+ }
+
+private:
+ struct Settings
+ {
+ Settings () : hideMetatables (true)
+ {
+ }
+
+ bool hideMetatables;
+ };
+
+ static Settings& getSettings ()
+ {
+ static Settings settings;
+ return settings;
+ }
+};
+
+#include "detail/Userdata.h"
+#include "detail/CFunctions.h"
+#include "detail/Namespace.h"
+
+//------------------------------------------------------------------------------
+/**
+ Push an object onto the Lua stack.
+*/
+template <class T>
+inline void push (lua_State* L, T t)
+{
+ Stack <T>::push (L, t);
+}
+
+//------------------------------------------------------------------------------
+/**
+ Set a global value in the lua_State.
+
+ @note This works on any type specialized by `Stack`, including `LuaRef` and
+ its table proxies.
+*/
+template <class T>
+inline void setGlobal (lua_State* L, T t, char const* name)
+{
+ push (L, t);
+ lua_setglobal (L, name);
+}
+
+//------------------------------------------------------------------------------
+/**
+ Change whether or not metatables are hidden (on by default).
+*/
+inline void setHideMetatables (bool shouldHide)
+{
+ Security::setHideMetatables (shouldHide);
+}
+
+}
+
+#endif
diff --git a/contrib/src/LuaBridge/RefCountedObject.h b/contrib/src/LuaBridge/RefCountedObject.h
new file mode 100644
index 0000000..807b460
--- /dev/null
+++ b/contrib/src/LuaBridge/RefCountedObject.h
@@ -0,0 +1,363 @@
+//==============================================================================
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2004-11 by Raw Material Software Ltd.
+
+ This is a derivative work used by permission from part of
+ JUCE, available at http://www.rawaterialsoftware.com
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ This file incorporates work covered by the following copyright and
+ permission notice:
+
+ This file is part of the JUCE library - "Jules' Utility Class Extensions"
+ Copyright 2004-11 by Raw Material Software Ltd.
+*/
+//==============================================================================
+
+#ifndef LUABRIDGE_REFCOUNTEDOBJECT_HEADER
+#define LUABRIDGE_REFCOUNTEDOBJECT_HEADER
+
+//#define LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
+
+#include <cassert>
+
+//==============================================================================
+/**
+ Adds reference-counting to an object.
+
+ To add reference-counting to a class, derive it from this class, and
+ use the RefCountedObjectPtr class to point to it.
+
+ e.g. @code
+ class MyClass : public RefCountedObjectType
+ {
+ void foo();
+
+ // This is a neat way of declaring a typedef for a pointer class,
+ // rather than typing out the full templated name each time..
+ typedef RefCountedObjectPtr<MyClass> Ptr;
+ };
+
+ MyClass::Ptr p = new MyClass();
+ MyClass::Ptr p2 = p;
+ p = 0;
+ p2->foo();
+ @endcode
+
+ Once a new RefCountedObjectType has been assigned to a pointer, be
+ careful not to delete the object manually.
+*/
+template <class CounterType>
+class RefCountedObjectType
+{
+public:
+ //==============================================================================
+ /** Increments the object's reference count.
+
+ This is done automatically by the smart pointer, but is public just
+ in case it's needed for nefarious purposes.
+ */
+ inline void incReferenceCount() const
+ {
+ ++refCount;
+ }
+
+ /** Decreases the object's reference count.
+
+ If the count gets to zero, the object will be deleted.
+ */
+ inline void decReferenceCount() const
+ {
+ assert (getReferenceCount() > 0);
+
+ if (--refCount == 0)
+ delete this;
+ }
+
+ /** Returns the object's current reference count. */
+ inline int getReferenceCount() const
+ {
+ return static_cast <int> (refCount);
+ }
+
+protected:
+ //==============================================================================
+ /** Creates the reference-counted object (with an initial ref count of zero). */
+ RefCountedObjectType() : refCount ()
+ {
+ }
+
+ /** Destructor. */
+ virtual ~RefCountedObjectType()
+ {
+ // it's dangerous to delete an object that's still referenced by something else!
+ assert (getReferenceCount() == 0);
+ }
+
+private:
+ //==============================================================================
+ CounterType mutable refCount;
+};
+
+//==============================================================================
+
+/** Non thread-safe reference counted object.
+
+ This creates a RefCountedObjectType that uses a non-atomic integer
+ as the counter.
+*/
+typedef RefCountedObjectType <int> RefCountedObject;
+
+//==============================================================================
+/**
+ A smart-pointer class which points to a reference-counted object.
+
+ The template parameter specifies the class of the object you want to point
+ to - the easiest way to make a class reference-countable is to simply make
+ it inherit from RefCountedObjectType, but if you need to, you could roll
+ your own reference-countable class by implementing a pair of methods called
+ incReferenceCount() and decReferenceCount().
+
+ When using this class, you'll probably want to create a typedef to
+ abbreviate the full templated name - e.g.
+
+ @code
+
+ typedef RefCountedObjectPtr <MyClass> MyClassPtr;
+
+ @endcode
+*/
+template <class ReferenceCountedObjectClass>
+class RefCountedObjectPtr
+{
+public:
+ /** The class being referenced by this pointer. */
+ typedef ReferenceCountedObjectClass ReferencedType;
+
+ //==============================================================================
+ /** Creates a pointer to a null object. */
+ inline RefCountedObjectPtr() : referencedObject (0)
+ {
+ }
+
+ /** Creates a pointer to an object.
+
+ This will increment the object's reference-count if it is non-null.
+ */
+ inline RefCountedObjectPtr (ReferenceCountedObjectClass* const refCountedObject)
+ : referencedObject (refCountedObject)
+ {
+ if (refCountedObject != 0)
+ refCountedObject->incReferenceCount();
+ }
+
+ /** Copies another pointer.
+ This will increment the object's reference-count (if it is non-null).
+ */
+ inline RefCountedObjectPtr (const RefCountedObjectPtr& other)
+ : referencedObject (other.referencedObject)
+ {
+ if (referencedObject != 0)
+ referencedObject->incReferenceCount();
+ }
+
+#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Takes-over the object from another pointer. */
+ inline RefCountedObjectPtr (RefCountedObjectPtr&& other)
+ : referencedObject (other.referencedObject)
+ {
+ other.referencedObject = 0;
+ }
+#endif
+
+ /** Copies another pointer.
+ This will increment the object's reference-count (if it is non-null).
+ */
+ template <class DerivedClass>
+ inline RefCountedObjectPtr (const RefCountedObjectPtr<DerivedClass>& other)
+ : referencedObject (static_cast <ReferenceCountedObjectClass*> (other.getObject()))
+ {
+ if (referencedObject != 0)
+ referencedObject->incReferenceCount();
+ }
+
+ /** Changes this pointer to point at a different object.
+
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other)
+ {
+ return operator= (other.referencedObject);
+ }
+
+ /** Changes this pointer to point at a different object.
+
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ template <class DerivedClass>
+ RefCountedObjectPtr& operator= (const RefCountedObjectPtr<DerivedClass>& other)
+ {
+ return operator= (static_cast <ReferenceCountedObjectClass*> (other.getObject()));
+ }
+
+#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Takes-over the object from another pointer. */
+ RefCountedObjectPtr& operator= (RefCountedObjectPtr&& other)
+ {
+ std::swap (referencedObject, other.referencedObject);
+ return *this;
+ }
+#endif
+
+ /** Changes this pointer to point at a different object.
+
+ The reference count of the old object is decremented, and it might be
+ deleted if it hits zero. The new object's count is incremented.
+ */
+ RefCountedObjectPtr& operator= (ReferenceCountedObjectClass* const newObject)
+ {
+ if (referencedObject != newObject)
+ {
+ if (newObject != 0)
+ newObject->incReferenceCount();
+
+ ReferenceCountedObjectClass* const oldObject = referencedObject;
+ referencedObject = newObject;
+
+ if (oldObject != 0)
+ oldObject->decReferenceCount();
+ }
+
+ return *this;
+ }
+
+ /** Destructor.
+
+ This will decrement the object's reference-count, and may delete it if it
+ gets to zero.
+ */
+ inline ~RefCountedObjectPtr()
+ {
+ if (referencedObject != 0)
+ referencedObject->decReferenceCount();
+ }
+
+ /** Returns the object that this pointer references.
+ The pointer returned may be zero, of course.
+ */
+ inline operator ReferenceCountedObjectClass*() const
+ {
+ return referencedObject;
+ }
+
+ // the -> operator is called on the referenced object
+ inline ReferenceCountedObjectClass* operator->() const
+ {
+ return referencedObject;
+ }
+
+ /** Returns the object that this pointer references.
+ The pointer returned may be zero, of course.
+ */
+ inline ReferenceCountedObjectClass* getObject() const
+ {
+ return referencedObject;
+ }
+
+private:
+ //==============================================================================
+ ReferenceCountedObjectClass* referencedObject;
+};
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, ReferenceCountedObjectClass* const object2)
+{
+ return object1.getObject() == object2;
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, const RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
+{
+ return object1.getObject() == object2.getObject();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator== (ReferenceCountedObjectClass* object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
+{
+ return object1 == object2.getObject();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectClass* object2)
+{
+ return object1.getObject() != object2;
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
+{
+ return object1.getObject() != object2.getObject();
+}
+
+/** Compares two ReferenceCountedObjectPointers. */
+template <class ReferenceCountedObjectClass>
+bool operator!= (ReferenceCountedObjectClass* object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
+{
+ return object1 != object2.getObject();
+}
+
+//==============================================================================
+
+namespace luabridge
+{
+
+// forward declaration
+template <class T>
+struct ContainerTraits;
+
+template <class T>
+struct ContainerTraits <RefCountedObjectPtr <T> >
+{
+ typedef T Type;
+
+ static T* get (RefCountedObjectPtr <T> const& c)
+ {
+ return c.getObject ();
+ }
+};
+
+}
+
+//==============================================================================
+
+#endif
+
diff --git a/contrib/src/LuaBridge/RefCountedPtr.h b/contrib/src/LuaBridge/RefCountedPtr.h
new file mode 100644
index 0000000..7c27ca4
--- /dev/null
+++ b/contrib/src/LuaBridge/RefCountedPtr.h
@@ -0,0 +1,251 @@
+//==============================================================================
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef LUABRIDGE_REFCOUNTEDPTR_HEADER
+#define LUABRIDGE_REFCOUNTEDPTR_HEADER
+
+#ifdef _MSC_VER
+# include <hash_map>
+#else
+# include <stdint.h>
+# include <ext/hash_map>
+#endif
+
+//==============================================================================
+/**
+ Support for our RefCountedPtr.
+*/
+struct RefCountedPtrBase
+{
+ // Declaration of container for the refcounts
+#ifdef _MSC_VER
+ typedef stdext::hash_map <const void *, int> RefCountsType;
+#else
+ struct ptr_hash
+ {
+ size_t operator () (const void * const v) const
+ {
+ static __gnu_cxx::hash<unsigned int> H;
+ return H(uintptr_t(v));
+ }
+ };
+ typedef __gnu_cxx::hash_map<const void *, int, ptr_hash> RefCountsType;
+#endif
+
+protected:
+ inline RefCountsType& getRefCounts ()
+ {
+ static RefCountsType refcounts;
+ return refcounts ;
+ }
+};
+
+//==============================================================================
+/**
+ A reference counted smart pointer.
+
+ The api is compatible with boost::RefCountedPtr and std::RefCountedPtr, in the
+ sense that it implements a strict subset of the functionality.
+
+ This implementation uses a hash table to look up the reference count
+ associated with a particular pointer.
+
+ @tparam T The class type.
+
+ @todo Decompose RefCountedPtr using a policy. At a minimum, the underlying
+ reference count should be policy based (to support atomic operations)
+ and the delete behavior should be policy based (to support custom
+ disposal methods).
+
+ @todo Provide an intrusive version of RefCountedPtr.
+*/
+template <class T>
+class RefCountedPtr : private RefCountedPtrBase
+{
+public:
+ template <typename Other>
+ struct rebind
+ {
+ typedef RefCountedPtr <Other> other;
+ };
+
+ /** Construct as nullptr or from existing pointer to T.
+
+ @param p The optional, existing pointer to assign from.
+ */
+ RefCountedPtr (T* p = 0) : m_p (p)
+ {
+ ++getRefCounts () [m_p];
+ }
+
+ /** Construct from another RefCountedPtr.
+
+ @param rhs The RefCountedPtr to assign from.
+ */
+ RefCountedPtr (RefCountedPtr <T> const& rhs) : m_p (rhs.get())
+ {
+ ++getRefCounts () [m_p];
+ }
+
+ /** Construct from a RefCountedPtr of a different type.
+
+ @invariant A pointer to U must be convertible to a pointer to T.
+
+ @param rhs The RefCountedPtr to assign from.
+ @tparam U The other object type.
+ */
+ template <typename U>
+ RefCountedPtr (RefCountedPtr <U> const& rhs) : m_p (static_cast <T*> (rhs.get()))
+ {
+ ++getRefCounts () [m_p];
+ }
+
+ /** Release the object.
+
+ If there are no more references then the object is deleted.
+ */
+ ~RefCountedPtr ()
+ {
+ reset();
+ }
+
+ /** Assign from another RefCountedPtr.
+
+ @param rhs The RefCountedPtr to assign from.
+ @return A reference to the RefCountedPtr.
+ */
+ RefCountedPtr <T>& operator= (RefCountedPtr <T> const& rhs)
+ {
+ if (m_p != rhs.m_p)
+ {
+ reset ();
+ m_p = rhs.m_p;
+ ++getRefCounts () [m_p];
+ }
+ return *this;
+ }
+
+ /** Assign from another RefCountedPtr of a different type.
+
+ @note A pointer to U must be convertible to a pointer to T.
+
+ @tparam U The other object type.
+ @param rhs The other RefCountedPtr to assign from.
+ @return A reference to the RefCountedPtr.
+ */
+ template <typename U>
+ RefCountedPtr <T>& operator= (RefCountedPtr <U> const& rhs)
+ {
+ reset ();
+ m_p = static_cast <T*> (rhs.get());
+ ++getRefCounts () [m_p];
+ return *this;
+ }
+
+ /** Retrieve the raw pointer.
+
+ @return A pointer to the object.
+ */
+ T* get () const
+ {
+ return m_p;
+ }
+
+ /** Retrieve the raw pointer.
+
+ @return A pointer to the object.
+ */
+ T* operator* () const
+ {
+ return m_p;
+ }
+
+ /** Retrieve the raw pointer.
+
+ @return A pointer to the object.
+ */
+ T* operator-> () const
+ {
+ return m_p;
+ }
+
+ /** Determine the number of references.
+
+ @note This is not thread-safe.
+
+ @return The number of active references.
+ */
+ long use_count () const
+ {
+ return getRefCounts () [m_p];
+ }
+
+ /** Release the pointer.
+
+ The reference count is decremented. If the reference count reaches
+ zero, the object is deleted.
+ */
+ void reset ()
+ {
+ if (m_p != 0)
+ {
+ if (--getRefCounts () [m_p] <= 0)
+ delete m_p;
+
+ m_p = 0;
+ }
+ }
+
+private:
+ T* m_p;
+};
+
+//==============================================================================
+
+namespace luabridge
+{
+
+// forward declaration
+template <class T>
+struct ContainerTraits;
+
+template <class T>
+struct ContainerTraits <RefCountedPtr <T> >
+{
+ typedef T Type;
+
+ static T* get (RefCountedPtr <T> const& c)
+ {
+ return c.get ();
+ }
+};
+
+}
+
+#endif
diff --git a/contrib/src/LuaBridge/detail/CFunctions.h b/contrib/src/LuaBridge/detail/CFunctions.h
new file mode 100644
index 0000000..0497b6b
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/CFunctions.h
@@ -0,0 +1,442 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+// We use a structure so we can define everything in the header.
+//
+struct CFunc
+{
+ //----------------------------------------------------------------------------
+ /**
+ __index metamethod for a namespace or class static members.
+
+ This handles:
+ Retrieving functions and class static methods, stored in the metatable.
+ Reading global and class static data, stored in the __propget table.
+ Reading global and class properties, stored in the __propget table.
+ */
+ static int indexMetaMethod (lua_State* L)
+ {
+ int result = 0;
+ lua_getmetatable (L, 1); // push metatable of arg1
+ for (;;)
+ {
+ lua_pushvalue (L, 2); // push key arg2
+ lua_rawget (L, -2); // lookup key in metatable
+ if (lua_isnil (L, -1)) // not found
+ {
+ lua_pop (L, 1); // discard nil
+ rawgetfield (L, -1, "__propget"); // lookup __propget in metatable
+ lua_pushvalue (L, 2); // push key arg2
+ lua_rawget (L, -2); // lookup key in __propget
+ lua_remove (L, -2); // discard __propget
+ if (lua_iscfunction (L, -1))
+ {
+ lua_remove (L, -2); // discard metatable
+ lua_pushvalue (L, 1); // push arg1
+ lua_call (L, 1, 1); // call cfunction
+ result = 1;
+ break;
+ }
+ else
+ {
+ assert (lua_isnil (L, -1));
+ lua_pop (L, 1); // discard nil and fall through
+ }
+ }
+ else
+ {
+ assert (lua_istable (L, -1) || lua_iscfunction (L, -1));
+ lua_remove (L, -2);
+ result = 1;
+ break;
+ }
+
+ rawgetfield (L, -1, "__parent");
+ if (lua_istable (L, -1))
+ {
+ // Remove metatable and repeat the search in __parent.
+ lua_remove (L, -2);
+ }
+ else
+ {
+ // Discard metatable and return nil.
+ assert (lua_isnil (L, -1));
+ lua_remove (L, -2);
+ result = 1;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ __newindex metamethod for a namespace or class static members.
+
+ The __propset table stores proxy functions for assignment to:
+ Global and class static data.
+ Global and class properties.
+ */
+ static int newindexMetaMethod (lua_State* L)
+ {
+ int result = 0;
+ lua_getmetatable (L, 1); // push metatable of arg1
+ for (;;)
+ {
+ rawgetfield (L, -1, "__propset"); // lookup __propset in metatable
+ assert (lua_istable (L, -1));
+ lua_pushvalue (L, 2); // push key arg2
+ lua_rawget (L, -2); // lookup key in __propset
+ lua_remove (L, -2); // discard __propset
+ if (lua_iscfunction (L, -1)) // ensure value is a cfunction
+ {
+ lua_remove (L, -2); // discard metatable
+ lua_pushvalue (L, 3); // push new value arg3
+ lua_call (L, 1, 0); // call cfunction
+ result = 0;
+ break;
+ }
+ else
+ {
+ assert (lua_isnil (L, -1));
+ lua_pop (L, 1);
+ }
+
+ rawgetfield (L, -1, "__parent");
+ if (lua_istable (L, -1))
+ {
+ // Remove metatable and repeat the search in __parent.
+ lua_remove (L, -2);
+ }
+ else
+ {
+ assert (lua_isnil (L, -1));
+ lua_pop (L, 2);
+ result = luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2));
+ }
+ }
+
+ return result;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to report an error writing to a read-only value.
+
+ The name of the variable is in the first upvalue.
+ */
+ static int readOnlyError (lua_State* L)
+ {
+ std::string s;
+
+ s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only";
+
+ return luaL_error (L, s.c_str ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to get a variable.
+
+ This is used for global variables or class static data members.
+
+ The pointer to the data is in the first upvalue.
+ */
+ template <class T>
+ static int getVariable (lua_State* L)
+ {
+ assert (lua_islightuserdata (L, lua_upvalueindex (1)));
+ T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (ptr != 0);
+ Stack <T>::push (L, *ptr);
+ return 1;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to set a variable.
+
+ This is used for global variables or class static data members.
+
+ The pointer to the data is in the first upvalue.
+ */
+ template <class T>
+ static int setVariable (lua_State* L)
+ {
+ assert (lua_islightuserdata (L, lua_upvalueindex (1)));
+ T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (ptr != 0);
+ *ptr = Stack <T>::get (L, 1);
+ return 0;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a function with a return value.
+
+ This is used for global functions, global properties, class static methods,
+ and class static properties.
+
+ The function pointer is in the first upvalue.
+ */
+ template <class FnPtr,
+ class ReturnType = typename FuncTraits <FnPtr>::ReturnType>
+ struct Call
+ {
+ typedef typename FuncTraits <FnPtr>::Params Params;
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ ArgList <Params> args (L);
+ Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args));
+ return 1;
+ }
+ };
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a function with no return value.
+
+ This is used for global functions, global properties, class static methods,
+ and class static properties.
+
+ The function pointer is in the first upvalue.
+ */
+ template <class FnPtr>
+ struct Call <FnPtr, void>
+ {
+ typedef typename FuncTraits <FnPtr>::Params Params;
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ ArgList <Params> args (L);
+ FuncTraits <FnPtr>::call (fnptr, args);
+ return 0;
+ }
+ };
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a class member function with a return value.
+
+ The member function pointer is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class MemFnPtr,
+ class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
+ struct CallMember
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ T* const t = Userdata::get <T> (L, 1, false);
+ MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ ArgList <Params, 2> args (L);
+ Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
+ return 1;
+ }
+ };
+
+ template <class MemFnPtr,
+ class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
+ struct CallConstMember
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ T const* const t = Userdata::get <T> (L, 1, true);
+ MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ ArgList <Params, 2> args(L);
+ Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
+ return 1;
+ }
+ };
+
+ //----------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a class member function with no return value.
+
+ The member function pointer is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class MemFnPtr>
+ struct CallMember <MemFnPtr, void>
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ T* const t = Userdata::get <T> (L, 1, false);
+ MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ ArgList <Params, 2> args (L);
+ FuncTraits <MemFnPtr>::call (t, fnptr, args);
+ return 0;
+ }
+ };
+
+ template <class MemFnPtr>
+ struct CallConstMember <MemFnPtr, void>
+ {
+ typedef typename FuncTraits <MemFnPtr>::ClassType T;
+ typedef typename FuncTraits <MemFnPtr>::Params Params;
+
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ T const* const t = Userdata::get <T> (L, 1, true);
+ MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ ArgList <Params, 2> args (L);
+ FuncTraits <MemFnPtr>::call (t, fnptr, args);
+ return 0;
+ }
+ };
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to call a class member lua_CFunction.
+
+ The member function pointer is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class T>
+ struct CallMemberCFunction
+ {
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ typedef int (T::*MFP)(lua_State* L);
+ T* const t = Userdata::get <T> (L, 1, false);
+ MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ return (t->*fnptr) (L);
+ }
+ };
+
+ template <class T>
+ struct CallConstMemberCFunction
+ {
+ static int f (lua_State* L)
+ {
+ assert (isfulluserdata (L, lua_upvalueindex (1)));
+ typedef int (T::*MFP)(lua_State* L);
+ T const* const t = Userdata::get <T> (L, 1, true);
+ MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
+ assert (fnptr != 0);
+ return (t->*fnptr) (L);
+ }
+ };
+
+ //--------------------------------------------------------------------------
+
+ // SFINAE Helpers
+
+ template <class MemFnPtr, bool isConst>
+ struct CallMemberFunctionHelper
+ {
+ static void add (lua_State* L, char const* name, MemFnPtr mf)
+ {
+ new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
+ lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1);
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -5, name); // const table
+ rawsetfield (L, -3, name); // class table
+ }
+ };
+
+ template <class MemFnPtr>
+ struct CallMemberFunctionHelper <MemFnPtr, false>
+ {
+ static void add (lua_State* L, char const* name, MemFnPtr mf)
+ {
+ new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
+ lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1);
+ rawsetfield (L, -3, name); // class table
+ }
+ };
+
+ //--------------------------------------------------------------------------
+ /**
+ __gc metamethod for a class.
+ */
+ template <class C>
+ static int gcMetaMethod (lua_State* L)
+ {
+ Userdata* const ud = Userdata::getExact <C> (L, 1);
+ ud->~Userdata ();
+ return 0;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to get a class data member.
+
+ The pointer-to-member is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class C, typename T>
+ static int getProperty (lua_State* L)
+ {
+ C const* const c = Userdata::get <C> (L, 1, true);
+ T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+ Stack <T>::push (L, c->**mp);
+ return 1;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to set a class data member.
+
+ The pointer-to-member is in the first upvalue.
+ The class userdata object is at the top of the Lua stack.
+ */
+ template <class C, typename T>
+ static int setProperty (lua_State* L)
+ {
+ C* const c = Userdata::get <C> (L, 1, false);
+ T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+ c->**mp = Stack <T>::get (L, 2);
+ return 0;
+ }
+};
diff --git a/contrib/src/LuaBridge/detail/ClassInfo.h b/contrib/src/LuaBridge/detail/ClassInfo.h
new file mode 100644
index 0000000..8d58069
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/ClassInfo.h
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+/** Unique Lua registry keys for a class.
+
+ Each registered class inserts three keys into the registry, whose
+ values are the corresponding static, class, and const metatables. This
+ allows a quick and reliable lookup for a metatable from a template type.
+*/
+template <class T>
+class ClassInfo
+{
+public:
+ /** Get the key for the static table.
+
+ The static table holds the static data members, static properties, and
+ static member functions for a class.
+ */
+ static void const* getStaticKey ()
+ {
+ static char value;
+ return &value;
+ }
+
+ /** Get the key for the class table.
+
+ The class table holds the data members, properties, and member functions
+ of a class. Read-only data and properties, and const member functions are
+ also placed here (to save a lookup in the const table).
+ */
+ static void const* getClassKey ()
+ {
+ static char value;
+ return &value;
+ }
+
+ /** Get the key for the const table.
+
+ The const table holds read-only data members and properties, and const
+ member functions of a class.
+ */
+ static void const* getConstKey ()
+ {
+ static char value;
+ return &value;
+ }
+};
+
diff --git a/contrib/src/LuaBridge/detail/Constructor.h b/contrib/src/LuaBridge/detail/Constructor.h
new file mode 100644
index 0000000..7b2dad0
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/Constructor.h
@@ -0,0 +1,204 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef LUABRIDGE_CONSTRUCTOR_HEADER
+#define LUABRIDGE_CONSTRUCTOR_HEADER
+
+/*
+* Constructor generators. These templates allow you to call operator new and
+* pass the contents of a type/value list to the Constructor. Like the
+* function pointer containers, these are only defined up to 8 parameters.
+*/
+
+/** Constructor generators.
+
+ These templates call operator new with the contents of a type/value
+ list passed to the Constructor with up to 8 parameters. Two versions
+ of call() are provided. One performs a regular new, the other performs
+ a placement new.
+*/
+template <class T, typename List>
+struct Constructor {};
+
+template <class T>
+struct Constructor <T, None>
+{
+ static T* call (TypeListValues <None> const&)
+ {
+ return new T;
+ }
+ static T* call (void* mem, TypeListValues <None> const&)
+ {
+ return new (mem) T;
+ }
+};
+
+template <class T, class P1>
+struct Constructor <T, TypeList <P1> >
+{
+ static T* call (const TypeListValues<TypeList <P1> > &tvl)
+ {
+ return new T(tvl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1> > &tvl)
+ {
+ return new (mem) T(tvl.hd);
+ }
+};
+
+template <class T, class P1, class P2>
+struct Constructor <T, TypeList <P1, TypeList <P2> > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3> > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3> > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3> > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4> > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4> > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4> > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4,
+ class P5>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4, TypeList <P5> > > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4,
+ class P5, class P6>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4, TypeList <P5, TypeList <P6> > > > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4,
+ class P5, class P6, class P7>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
+ TypeList <P7> > > > > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
+ TypeList <P7> > > > > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class P1, class P2, class P3, class P4,
+ class P5, class P6, class P7, class P8>
+struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
+ TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7,
+ TypeList <P8> > > > > > > > >
+{
+ static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
+ TypeList <P7, TypeList <P8> > > > > > > > > &tvl)
+ {
+ return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+ static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
+ TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
+ TypeList <P7, TypeList <P8> > > > > > > > > &tvl)
+ {
+ return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+#endif
diff --git a/contrib/src/LuaBridge/detail/FuncTraits.h b/contrib/src/LuaBridge/detail/FuncTraits.h
new file mode 100644
index 0000000..7eccb61
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/FuncTraits.h
@@ -0,0 +1,852 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+/**
+ Since the throw specification is part of a function signature, the FuncTraits
+ family of templates needs to be specialized for both types. The
+ LUABRIDGE_THROWSPEC macro controls whether we use the 'throw ()' form, or
+ 'noexcept' (if C++11 is available) to distinguish the functions.
+*/
+#if defined (__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__clang__) || defined(__GNUC__) || \
+ (defined (_MSC_VER) && (_MSC_VER >= 1700))
+// Do not define LUABRIDGE_THROWSPEC since the Xcode and gcc compilers do not
+// distinguish the throw specification in the function signature.
+#else
+// Visual Studio 10 and earlier pay too much mind to useless throw() spec.
+//
+# define LUABRIDGE_THROWSPEC throw()
+#endif
+
+//==============================================================================
+/**
+ Traits for function pointers.
+
+ There are three types of functions: global, non-const member, and const
+ member. These templates determine the type of function, which class type it
+ belongs to if it is a class member, the const-ness if it is a member
+ function, and the type information for the return value and argument list.
+
+ Expansions are provided for functions with up to 8 parameters. This can be
+ manually extended, or expanded to an arbitrary amount using C++11 features.
+*/
+template <class MemFn, class D = MemFn>
+struct FuncTraits
+{
+};
+
+/* Ordinary function pointers. */
+
+template <class R, class D>
+struct FuncTraits <R (*) (), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (D fp, TypeListValues <Params>)
+ {
+ return fp ();
+ }
+};
+
+template <class R, class P1, class D>
+struct FuncTraits <R (*) (P1), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class D>
+struct FuncTraits <R (*) (P1, P2), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (*) (P1, P2, P3), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7, P8), D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+/* Non-const member function pointers. */
+
+template <class T, class R, class D>
+struct FuncTraits <R (T::*) (), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (T* obj, D fp, TypeListValues <Params>)
+ {
+ return (obj->*fp)();
+ }
+};
+
+template <class T, class R, class P1, class D>
+struct FuncTraits <R (T::*) (P1), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class D>
+struct FuncTraits <R (T::*) (P1, P2), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8), D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+/* Const member function pointers. */
+
+template <class T, class R, class D>
+struct FuncTraits <R (T::*) () const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (T const* obj, D fp, TypeListValues <Params>)
+ {
+ return (obj->*fp)();
+ }
+};
+
+template <class T, class R, class P1, class D>
+struct FuncTraits <R (T::*) (P1) const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class D>
+struct FuncTraits <R (T::*) (P1, P2) const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (T const* obj, R (T::*fp) (P1, P2) const,
+ TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3) const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4) const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) const, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+#if defined (LUABRIDGE_THROWSPEC)
+
+/* Ordinary function pointers. */
+
+template <class R, class D>
+struct FuncTraits <R (*) () LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (D fp, TypeListValues <Params> const&)
+ {
+ return fp ();
+ }
+};
+
+template <class R, class P1, class D>
+struct FuncTraits <R (*) (P1) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class D>
+struct FuncTraits <R (*) (P1, P2) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = false;
+ typedef D DeclType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (D fp, TypeListValues <Params> tvl)
+ {
+ return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+/* Non-const member function pointers with THROWSPEC. */
+
+template <class T, class R, class D>
+struct FuncTraits <R (T::*) () LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (T* obj, D fp, TypeListValues <Params> const&)
+ {
+ return (obj->*fp)();
+ }
+};
+
+template <class T, class R, class P1, class D>
+struct FuncTraits <R (T::*) (P1) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class D>
+struct FuncTraits <R (T::*) (P1, P2) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = false;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (T* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+/* Const member function pointers with THROWSPEC. */
+
+template <class T, class R, class D>
+struct FuncTraits <R (T::*) () const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef None Params;
+ static R call (T const* obj, D fp, TypeListValues <Params>)
+ {
+ return (obj->*fp)();
+ }
+};
+
+template <class T, class R, class P1, class D>
+struct FuncTraits <R (T::*) (P1) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1> Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class D>
+struct FuncTraits <R (T::*) (P1, P2) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2> > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
+ tvl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
+struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) const LUABRIDGE_THROWSPEC, D>
+{
+ static bool const isMemberFunction = true;
+ static bool const isConstMemberFunction = true;
+ typedef D DeclType;
+ typedef T ClassType;
+ typedef R ReturnType;
+ typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
+ static R call (T const* obj, D fp, TypeListValues <Params> tvl)
+ {
+ return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
+ }
+};
+
+#endif
diff --git a/contrib/src/LuaBridge/detail/Iterator.h b/contrib/src/LuaBridge/detail/Iterator.h
new file mode 100644
index 0000000..d883fb3
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/Iterator.h
@@ -0,0 +1,114 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+/** Allows table iteration.
+*/
+class Iterator
+{
+private:
+ lua_State* m_L;
+ LuaRef m_table;
+ LuaRef m_key;
+ LuaRef m_value;
+
+ void next ()
+ {
+ m_table.push(m_L);
+ m_key.push (m_L);
+ if (lua_next (m_L, -2))
+ {
+ m_value.pop (m_L);
+ m_key.pop (m_L);
+ }
+ else
+ {
+ m_key = Nil();
+ m_value = Nil();
+ }
+ lua_pop(m_L, 1);
+ }
+
+public:
+ explicit Iterator (LuaRef table)
+ : m_L (table.state ())
+ , m_table (table)
+ , m_key (table.state ()) // m_key is nil
+ , m_value (table.state ()) // m_value is nil
+ {
+ next (); // get the first (key, value) pair from table
+ }
+
+ lua_State* state () const
+ {
+ return m_L;
+ }
+
+ LuaRef operator* () const
+ {
+ return m_value;
+ }
+
+ LuaRef operator-> () const
+ {
+ return m_value;
+ }
+
+ Iterator& operator++ ()
+ {
+ if (isNil())
+ {
+ // if the iterator reaches the end, do nothing
+ return *this;
+ }
+ else
+ {
+ next();
+ return *this;
+ }
+ }
+
+ inline bool isNil () const
+ {
+ return m_key.isNil ();
+ }
+
+ inline LuaRef key () const
+ {
+ return m_key;
+ }
+
+ inline LuaRef value () const
+ {
+ return m_value;
+ }
+
+private:
+ // Don't use postfix increment, it is less efficient
+ Iterator operator++ (int);
+};
+
diff --git a/contrib/src/LuaBridge/detail/LuaException.h b/contrib/src/LuaBridge/detail/LuaException.h
new file mode 100644
index 0000000..a094496
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/LuaException.h
@@ -0,0 +1,113 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+class LuaException : public std::exception
+{
+private:
+ lua_State* m_L;
+ std::string m_what;
+
+public:
+ //----------------------------------------------------------------------------
+ /**
+ Construct a LuaException after a lua_pcall().
+ */
+ LuaException (lua_State* L, int /*code*/)
+ : m_L (L)
+ {
+ whatFromStack ();
+ }
+
+ //----------------------------------------------------------------------------
+
+ LuaException (lua_State *L,
+ char const*,
+ char const*,
+ long)
+ : m_L (L)
+ {
+ whatFromStack ();
+ }
+
+ //----------------------------------------------------------------------------
+
+ ~LuaException() throw ()
+ {
+ }
+
+ //----------------------------------------------------------------------------
+
+ char const* what() const throw ()
+ {
+ return m_what.c_str();
+ }
+
+ //============================================================================
+ /**
+ Throw an exception.
+
+ This centralizes all the exceptions thrown, so that we can set
+ breakpoints before the stack is unwound, or otherwise customize the
+ behavior.
+ */
+ template <class Exception>
+ static void Throw (Exception e)
+ {
+ throw e;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Wrapper for lua_pcall that throws.
+ */
+ static void pcall (lua_State* L, int nargs = 0, int nresults = 0, int msgh = 0)
+ {
+ int code = lua_pcall (L, nargs, nresults, msgh);
+
+ if (code != LUABRIDGE_LUA_OK)
+ Throw (LuaException (L, code));
+ }
+
+ //----------------------------------------------------------------------------
+
+protected:
+ void whatFromStack ()
+ {
+ if (lua_gettop (m_L) > 0)
+ {
+ char const* s = lua_tostring (m_L, -1);
+ m_what = s ? s : "";
+ }
+ else
+ {
+ // stack is empty
+ m_what = "missing error";
+ }
+ }
+};
diff --git a/contrib/src/LuaBridge/detail/LuaHelpers.h b/contrib/src/LuaBridge/detail/LuaHelpers.h
new file mode 100644
index 0000000..7bc84eb
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/LuaHelpers.h
@@ -0,0 +1,143 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+// These are for Lua versions prior to 5.2.0.
+//
+#if LUA_VERSION_NUM < 502
+inline int lua_absindex (lua_State* L, int idx)
+{
+ if (idx > LUA_REGISTRYINDEX && idx < 0)
+ return lua_gettop (L) + idx + 1;
+ else
+ return idx;
+}
+
+inline void lua_rawgetp (lua_State* L, int idx, void const* p)
+{
+ idx = lua_absindex (L, idx);
+ lua_pushlightuserdata (L, const_cast <void*> (p));
+ lua_rawget (L,idx);
+}
+
+inline void lua_rawsetp (lua_State* L, int idx, void const* p)
+{
+ idx = lua_absindex (L, idx);
+ lua_pushlightuserdata (L, const_cast <void*> (p));
+ // put key behind value
+ lua_insert (L, -2);
+ lua_rawset (L, idx);
+}
+
+#define LUA_OPEQ 1
+#define LUA_OPLT 2
+#define LUA_OPLE 3
+
+inline int lua_compare (lua_State* L, int idx1, int idx2, int op)
+{
+ switch (op)
+ {
+ case LUA_OPEQ:
+ return lua_equal (L, idx1, idx2);
+ break;
+
+ case LUA_OPLT:
+ return lua_lessthan (L, idx1, idx2);
+ break;
+
+ case LUA_OPLE:
+ return lua_equal (L, idx1, idx2) || lua_lessthan (L, idx1, idx2);
+ break;
+
+ default:
+ return 0;
+ };
+}
+
+inline int get_length (lua_State* L, int idx)
+{
+ return int (lua_objlen (L, idx));
+}
+
+#else
+inline int get_length (lua_State* L, int idx)
+{
+ lua_len (L, idx);
+ int len = int (luaL_checknumber (L, -1));
+ lua_pop (L, 1);
+ return len;
+}
+
+#endif
+
+#ifndef LUA_OK
+# define LUABRIDGE_LUA_OK 0
+#else
+# define LUABRIDGE_LUA_OK LUA_OK
+#endif
+
+/** Get a table value, bypassing metamethods.
+*/
+inline void rawgetfield (lua_State* L, int index, char const* key)
+{
+ assert (lua_istable (L, index));
+ index = lua_absindex (L, index);
+ lua_pushstring (L, key);
+ lua_rawget (L, index);
+}
+
+/** Set a table value, bypassing metamethods.
+*/
+inline void rawsetfield (lua_State* L, int index, char const* key)
+{
+ assert (lua_istable (L, index));
+ index = lua_absindex (L, index);
+ lua_pushstring (L, key);
+ lua_insert (L, -2);
+ lua_rawset (L, index);
+}
+
+/** Returns true if the value is a full userdata (not light).
+*/
+inline bool isfulluserdata (lua_State* L, int index)
+{
+ return lua_isuserdata (L, index) && !lua_islightuserdata (L, index);
+}
+
+/** Test lua_State objects for global equality.
+
+ This can determine if two different lua_State objects really point
+ to the same global state, such as when using coroutines.
+
+ @note This is used for assertions.
+*/
+inline bool equalstates (lua_State* L1, lua_State* L2)
+{
+ return lua_topointer (L1, LUA_REGISTRYINDEX) ==
+ lua_topointer (L2, LUA_REGISTRYINDEX);
+}
diff --git a/contrib/src/LuaBridge/detail/LuaRef.h b/contrib/src/LuaBridge/detail/LuaRef.h
new file mode 100644
index 0000000..e726bca
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/LuaRef.h
@@ -0,0 +1,1215 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+//------------------------------------------------------------------------------
+/**
+ Type tag for representing LUA_TNIL.
+
+ Construct one of these using `Nil()` to represent a Lua nil. This is faster
+ than creating a reference in the registry to nil. Example:
+
+ LuaRef t (LuaRef::createTable (L));
+ ...
+ t ["k"] = Nil(); // assign nil
+*/
+struct Nil
+{
+};
+
+//------------------------------------------------------------------------------
+/**
+ Lightweight reference to a Lua object.
+
+ The reference is maintained for the lifetime of the C++ object.
+*/
+class LuaRef
+{
+private:
+ class Proxy;
+ friend struct Stack <Proxy>;
+
+ //----------------------------------------------------------------------------
+ /**
+ Pop the Lua stack.
+
+ Pops the specified number of stack items on destruction. We use this
+ when returning objects, to avoid an explicit temporary variable, since
+ the destructor executes after the return statement. For example:
+
+ template <class U>
+ U cast (lua_State* L)
+ {
+ StackPop p (L, 1);
+ ...
+ return U (); // dtor called after this line
+ }
+
+ @note The `StackPop` object must always be a named local variable.
+ */
+ class StackPop
+ {
+ public:
+ /** Create a StackPop object.
+
+ @param count The number of stack entries to pop on destruction.
+ */
+ StackPop (lua_State* L, int count)
+ : m_L (L)
+ , m_count (count)
+ {
+ }
+
+ ~StackPop ()
+ {
+ lua_pop (m_L, m_count);
+ }
+
+ private:
+ lua_State* m_L;
+ int m_count;
+ };
+
+ //----------------------------------------------------------------------------
+ /**
+ A proxy for representing table values.
+ */
+ class Proxy
+ {
+ private:
+ lua_State* m_L;
+ int m_tableRef;
+ int m_keyRef;
+
+ public:
+ //--------------------------------------------------------------------------
+ /**
+ Construct a Proxy from a table value.
+
+ The table is in the registry, and the key is at the top of the stack.
+ The key is popped off the stack.
+ */
+ Proxy (lua_State* L, int tableRef)
+ : m_L (L)
+ , m_tableRef (tableRef)
+ , m_keyRef (luaL_ref (L, LUA_REGISTRYINDEX))
+ {
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Create a Proxy via copy constructor.
+
+ It is best to avoid code paths that invoke this, because it creates
+ an extra temporary Lua reference. Typically this is done by passing
+ the Proxy parameter as a `const` reference.
+ */
+ Proxy (Proxy const& other)
+ : m_L (other.m_L)
+ , m_tableRef (other.m_tableRef)
+ {
+ // If this assert goes off it means code is taking this path,
+ // which is better avoided.
+ //
+ assert (0);
+
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_keyRef);
+ m_keyRef = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Destroy the proxy.
+
+ This does not destroy the table value.
+ */
+ ~Proxy ()
+ {
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_keyRef);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Return a reference to the table value.
+ */
+ int createRef () const
+ {
+ push (m_L);
+ return luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Assign a new value to this table key.
+
+ This may invoke metamethods.
+ */
+ template <class T>
+ Proxy& operator= (T v)
+ {
+ StackPop p (m_L, 1);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
+ Stack <T>::push (m_L, v);
+ lua_rawset (m_L, -3);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Assign a new value to this table key.
+
+ The assignment is raw, no metamethods are invoked.
+ */
+ template <class T>
+ Proxy& rawset (T v)
+ {
+ StackPop p (m_L, 1);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
+ lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
+ Stack <T>::push (m_L, v);
+ lua_settable (m_L, -3);
+ return *this;
+ }
+
+ //==========================================================================
+ //
+ // This group of member functions mirrors the member functions in LuaRef.
+
+ /** Retrieve the lua_State associated with the table value.
+ */
+ lua_State* state () const
+ {
+ return m_L;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Push the value onto the Lua stack.
+ */
+ void push (lua_State* L) const
+ {
+ assert (equalstates (L, m_L));
+ lua_rawgeti (L, LUA_REGISTRYINDEX, m_tableRef);
+ lua_rawgeti (L, LUA_REGISTRYINDEX, m_keyRef);
+ lua_gettable (L, -2);
+ lua_remove (L, -2); // remove the table
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Determine the object type.
+
+ The return values are the same as for `lua_type`.
+ */
+ int type () const
+ {
+ int result;
+ push (m_L);
+ result = lua_type (m_L, -1);
+ lua_pop (m_L, 1);
+ return result;
+ }
+
+ inline bool isNil () const { return type () == LUA_TNIL; }
+ inline bool isNumber () const { return type () == LUA_TNUMBER; }
+ inline bool isString () const { return type () == LUA_TSTRING; }
+ inline bool isTable () const { return type () == LUA_TTABLE; }
+ inline bool isFunction () const { return type () == LUA_TFUNCTION; }
+ inline bool isUserdata () const { return type () == LUA_TUSERDATA; }
+ inline bool isThread () const { return type () == LUA_TTHREAD; }
+ inline bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; }
+
+ //--------------------------------------------------------------------------
+ /**
+ Perform an explicit conversion.
+ */
+ template <class T>
+ T cast () const
+ {
+ StackPop p (m_L, 1);
+ push (m_L);
+
+ // lua_gettop is used because Userdata::getClass() doesn't handle
+ // negative stack indexes.
+ //
+ return Stack <T>::get (m_L, lua_gettop (m_L));
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Universal implicit conversion operator.
+
+ NOTE: Visual Studio 2010 and 2012 have a bug where this function
+ is not used. See:
+
+ http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014
+ https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile
+
+ // This code snippet fails to compile in vs2010,vs2012
+ struct S {
+ template <class T> inline operator T () const { return T (); }
+ };
+ int main () {
+ S () || false;
+ return 0;
+ }
+ */
+ template <class T>
+ inline operator T () const
+ {
+ return cast <T> ();
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Universal comparison operators.
+ */
+ /** @{ */
+ template <class T>
+ bool operator== (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1;
+ }
+
+ template <class T>
+ bool operator< (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -2, -1, LUA_OPLT) == 1;
+ }
+
+ template <class T>
+ bool operator<= (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -2, -1, LUA_OPLE) == 1;
+ }
+
+ template <class T>
+ bool operator> (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -1, -2, LUA_OPLT) == 1;
+ }
+
+ template <class T>
+ bool operator>= (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -1, -2, LUA_OPLE) == 1;
+ }
+
+ template <class T>
+ bool rawequal (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_rawequal (m_L, -1, -2) == 1;
+ }
+ /** @} */
+
+ //--------------------------------------------------------------------------
+ /**
+ Access a table value using a key.
+
+ This invokes metamethods.
+ */
+ template <class T>
+ Proxy operator[] (T key) const
+ {
+ return LuaRef (*this) [key];
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Access a table value using a key.
+
+ The operation is raw, metamethods are not invoked. The result is
+ passed by value and may not be modified.
+ */
+ template <class T>
+ LuaRef rawget (T key) const
+ {
+ StackPop (m_L, 1);
+ push (m_L);
+ Stack <T>::push (m_L, key);
+ lua_rawget (m_L, -2);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Append a value to the table.
+
+ If the table is a sequence this will add another element to it.
+ */
+ template <class T>
+ void append (T v) const
+ {
+ push (m_L);
+ Stack <T>::push (m_L, v);
+ luaL_ref (m_L, -2);
+ lua_pop (m_L, 1);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Call the length operator.
+
+ This is identical to applying the Lua # operator.
+ */
+ int length () const
+ {
+ StackPop p (m_L, 1);
+ push (m_L);
+ return get_length (m_L, -1);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Call Lua code.
+
+ These overloads allow Lua code to be called with up to 8 parameters.
+ The return value is provided as a LuaRef (which may be LUA_REFNIL).
+ If an error occurs, a LuaException is thrown.
+ */
+ /** @{ */
+ LuaRef const operator() () const
+ {
+ push (m_L);
+ LuaException::pcall (m_L, 0, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1>
+ LuaRef const operator() (P1 p1) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ LuaException::pcall (m_L, 1, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2>
+ LuaRef const operator() (P1 p1, P2 p2) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ LuaException::pcall (m_L, 2, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ LuaException::pcall (m_L, 3, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ LuaException::pcall (m_L, 4, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ LuaException::pcall (m_L, 5, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ LuaException::pcall (m_L, 6, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6, class P7>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ Stack <P7>::push (m_L, p7);
+ LuaException::pcall (m_L, 7, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ Stack <P7>::push (m_L, p7);
+ Stack <P8>::push (m_L, p8);
+ LuaException::pcall (m_L, 8, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+ /** @} */
+
+ //==========================================================================
+ };
+
+private:
+ friend struct Stack <LuaRef>;
+
+ //----------------------------------------------------------------------------
+ /**
+ Type tag for stack construction.
+ */
+ struct FromStack { };
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to an object at the top of the Lua stack and pop it.
+
+ This constructor is private and not invoked directly.
+ Instead, use the `fromStack` function.
+
+ @note The object is popped.
+ */
+ LuaRef (lua_State* L, FromStack)
+ : m_L (L)
+ {
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to an object on the Lua stack.
+
+ This constructor is private and not invoked directly.
+ Instead, use the `fromStack` function.
+
+ @note The object is not popped.
+ */
+ LuaRef (lua_State* L, int index, FromStack)
+ : m_L (L)
+ {
+ lua_pushvalue (m_L, index);
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //----------------------------------------------------------------------------
+
+ // This type of construction is disallowed, since we don't have a `lua_State`.
+ //
+ template <class T>
+ LuaRef (T)
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to this ref.
+
+ This is used internally.
+ */
+ int createRef () const
+ {
+ if (m_ref != LUA_REFNIL)
+ {
+ push (m_L);
+ return luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+ else
+ {
+ return LUA_REFNIL;
+ }
+ }
+
+public:
+ //----------------------------------------------------------------------------
+ /**
+ Create a nil reference.
+
+ The LuaRef may be assigned later.
+ */
+ LuaRef (lua_State* L)
+ : m_L (L)
+ , m_ref (LUA_REFNIL)
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to a value.
+ */
+ template <class T>
+ LuaRef (lua_State* L, T v)
+ : m_L (L)
+ {
+ Stack <T>::push (m_L, v);
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a reference to a table value.
+ */
+ LuaRef (Proxy const& v)
+ : m_L (v.state ())
+ , m_ref (v.createRef ())
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a new reference to an existing reference.
+ */
+ LuaRef (LuaRef const& other)
+ : m_L (other.m_L)
+ , m_ref (other.createRef ())
+ {
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Destroy a reference.
+
+ The corresponding Lua registry reference will be released.
+
+ @note If the state refers to a thread, it is the responsibility of the
+ caller to ensure that the thread still exists when the LuaRef
+ is destroyed.
+ */
+ ~LuaRef ()
+ {
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Return a LuaRef from a stack item.
+
+ The stack item is not popped.
+ */
+ static LuaRef fromStack (lua_State* L, int index)
+ {
+ lua_pushvalue (L, index);
+ return LuaRef (L, FromStack ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Create a new empty table and return a reference to it.
+
+ It is also possible to use the free function `newTable`.
+
+ @see ::getGlobal
+ */
+ static LuaRef newTable (lua_State* L)
+ {
+ lua_newtable (L);
+ return LuaRef (L, FromStack ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Return a reference to a named global.
+
+ It is also possible to use the free function `getGlobal`.
+
+ @see ::getGlobal
+ */
+ static LuaRef getGlobal (lua_State *L, char const* name)
+ {
+ lua_getglobal (L, name);
+ return LuaRef (L, FromStack ());
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Assign a different value to this LuaRef.
+ */
+ template <class T>
+ LuaRef& operator= (T rhs)
+ {
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
+ Stack <T>::push (m_L, rhs);
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Assign another LuaRef to this LuaRef.
+ */
+ LuaRef& operator= (LuaRef const& rhs)
+ {
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
+ rhs.push (m_L);
+ m_L = rhs.state ();
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ converts to a string using luas tostring function
+ */
+ std::string tostring() const
+ {
+ lua_getglobal (m_L, "tostring");
+ push (m_L);
+ lua_call (m_L, 1, 1);
+ const char* str = lua_tostring(m_L, 1);
+ lua_pop(m_L, 1);
+ return std::string(str);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Print a text description of the value to a stream.
+
+ This is used for diagnostics.
+ */
+ void print (std::ostream& os) const
+ {
+ switch (type ())
+ {
+ case LUA_TNIL:
+ os << "nil";
+ break;
+
+ case LUA_TNUMBER:
+ os << cast <lua_Number> ();
+ break;
+
+ case LUA_TBOOLEAN:
+ os << (cast <bool> () ? "true" : "false");
+ break;
+
+ case LUA_TSTRING:
+ os << '"' << cast <std::string> () << '"';
+ break;
+
+ case LUA_TTABLE:
+ os << "table: " << tostring();
+ break;
+
+ case LUA_TFUNCTION:
+ os << "function: " << tostring();
+ break;
+
+ case LUA_TUSERDATA:
+ os << "userdata: " << tostring();
+ break;
+
+ case LUA_TTHREAD:
+ os << "thread: " << tostring();
+ break;
+
+ case LUA_TLIGHTUSERDATA:
+ os << "lightuserdata: " << tostring();
+ break;
+
+ default:
+ os << "unknown";
+ break;
+ }
+ }
+
+ //============================================================================
+ //
+ // This group of member functions is mirrored in Proxy
+ //
+
+ /** Retrieve the lua_State associated with the reference.
+ */
+ lua_State* state () const
+ {
+ return m_L;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Place the object onto the Lua stack.
+ */
+ void push (lua_State* L) const
+ {
+ assert (equalstates (L, m_L));
+ lua_rawgeti (L, LUA_REGISTRYINDEX, m_ref);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Pop the top of Lua stack and assign the ref to m_ref
+ */
+ void pop (lua_State* L)
+ {
+ assert (equalstates (L, m_L));
+ luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
+ m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Determine the object type.
+
+ The return values are the same as for `lua_type`.
+ */
+ /** @{ */
+ int type () const
+ {
+ int result;
+ if (m_ref != LUA_REFNIL)
+ {
+ push (m_L);
+ result = lua_type (m_L, -1);
+ lua_pop (m_L, 1);
+ }
+ else
+ {
+ result = LUA_TNIL;
+ }
+
+ return result;
+ }
+
+ // should never happen
+ //inline bool isNone () const { return m_ref == LUA_NOREF; }
+
+ inline bool isNil () const { return type () == LUA_TNIL; }
+ inline bool isNumber () const { return type () == LUA_TNUMBER; }
+ inline bool isString () const { return type () == LUA_TSTRING; }
+ inline bool isTable () const { return type () == LUA_TTABLE; }
+ inline bool isFunction () const { return type () == LUA_TFUNCTION; }
+ inline bool isUserdata () const { return type () == LUA_TUSERDATA; }
+ inline bool isThread () const { return type () == LUA_TTHREAD; }
+ inline bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; }
+ /** @} */
+
+ //----------------------------------------------------------------------------
+ /**
+ Perform an explicit conversion.
+ */
+ template <class T>
+ T cast () const
+ {
+ StackPop p (m_L, 1);
+ push (m_L);
+
+ // lua_gettop is used because Userdata::getClass() doesn't handle
+ // negative stack indexes.
+ //
+ return Stack <T>::get (m_L, lua_gettop (m_L));
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Universal implicit conversion operator.
+
+ NOTE: Visual Studio 2010 and 2012 have a bug where this function
+ is not used. See:
+
+ http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014
+ https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile
+
+ // This code snippet fails to compile in vs2010,vs2012
+ struct S {
+ template <class T> inline operator T () const { return T (); }
+ };
+ int main () {
+ S () || false;
+ return 0;
+ }
+ */
+ template <class T>
+ inline operator T () const
+ {
+ return cast <T> ();
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Universal comparison operators.
+ */
+ /** @{ */
+ template <class T>
+ bool operator== (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1;
+ }
+
+ template <class T>
+ bool operator< (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -2, -1, LUA_OPLT) == 1;
+ }
+
+ template <class T>
+ bool operator<= (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -2, -1, LUA_OPLE) == 1;
+ }
+
+ template <class T>
+ bool operator> (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -1, -2, LUA_OPLT) == 1;
+ }
+
+ template <class T>
+ bool operator>= (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_compare (m_L, -1, -2, LUA_OPLE) == 1;
+ }
+
+ template <class T>
+ bool rawequal (T rhs) const
+ {
+ StackPop p (m_L, 2);
+ push (m_L);
+ Stack <T>::push (m_L, rhs);
+ return lua_rawequal (m_L, -1, -2) == 1;
+ }
+ /** @} */
+
+ //----------------------------------------------------------------------------
+ /**
+ Append a value to the table.
+
+ If the table is a sequence this will add another element to it.
+ */
+ template <class T>
+ void append (T v) const
+ {
+ push (m_L);
+ Stack <T>::push (m_L, v);
+ luaL_ref (m_L, -2);
+ lua_pop (m_L, 1);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Call the length operator.
+
+ This is identical to applying the Lua # operator.
+ */
+ int length () const
+ {
+ StackPop p (m_L, 1);
+ push (m_L);
+ return get_length (m_L, -1);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Access a table value using a key.
+
+ This invokes metamethods.
+ */
+ template <class T>
+ Proxy operator[] (T key) const
+ {
+ Stack <T>::push (m_L, key);
+ return Proxy (m_L, m_ref);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Call Lua code.
+
+ These overloads allow Lua code to be called with up to 8 parameters.
+ The return value is provided as a LuaRef (which may be LUA_REFNIL).
+ If an error occurs, a LuaException is thrown.
+ */
+ /** @{ */
+ LuaRef const operator() () const
+ {
+ push (m_L);
+ LuaException::pcall (m_L, 0, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1>
+ LuaRef const operator() (P1 p1) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ LuaException::pcall (m_L, 1, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2>
+ LuaRef const operator() (P1 p1, P2 p2) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ LuaException::pcall (m_L, 2, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ LuaException::pcall (m_L, 3, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ LuaException::pcall (m_L, 4, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ LuaException::pcall (m_L, 5, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ LuaException::pcall (m_L, 6, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6, class P7>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ Stack <P7>::push (m_L, p7);
+ LuaException::pcall (m_L, 7, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
+ LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const
+ {
+ push (m_L);
+ Stack <P1>::push (m_L, p1);
+ Stack <P2>::push (m_L, p2);
+ Stack <P3>::push (m_L, p3);
+ Stack <P4>::push (m_L, p4);
+ Stack <P5>::push (m_L, p5);
+ Stack <P6>::push (m_L, p6);
+ Stack <P7>::push (m_L, p7);
+ Stack <P8>::push (m_L, p8);
+ LuaException::pcall (m_L, 8, 1);
+ return LuaRef (m_L, FromStack ());
+ }
+ /** @} */
+
+ //============================================================================
+
+private:
+ lua_State* m_L;
+ int m_ref;
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for Nil
+*/
+template <>
+struct Stack <Nil>
+{
+public:
+ static inline void push (lua_State* L, Nil)
+ {
+ lua_pushnil (L);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for LuaRef.
+*/
+template <>
+struct Stack <LuaRef>
+{
+public:
+ // The value is const& to prevent a copy construction.
+ //
+ static inline void push (lua_State* L, LuaRef const& v)
+ {
+ v.push (L);
+ }
+
+ static inline LuaRef get (lua_State* L, int index)
+ {
+ return LuaRef (L, index, LuaRef::FromStack ());
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for Proxy.
+*/
+template <>
+struct Stack <LuaRef::Proxy>
+{
+public:
+ // The value is const& to prevent a copy construction.
+ //
+ static inline void push (lua_State* L, LuaRef::Proxy const& v)
+ {
+ v.push (L);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Create a reference to a new, empty table.
+
+ This is a syntactic abbreviation for LuaRef::newTable().
+*/
+inline LuaRef newTable (lua_State* L)
+{
+ return LuaRef::newTable (L);
+}
+
+//------------------------------------------------------------------------------
+/**
+ Create a reference to a value in the global table.
+
+ This is a syntactic abbreviation for LuaRef::getGlobal().
+*/
+inline LuaRef getGlobal (lua_State *L, char const* name)
+{
+ return LuaRef::getGlobal (L, name);
+}
+
+//------------------------------------------------------------------------------
+/**
+ Write a LuaRef to a stream.
+
+ This allows LuaRef and table proxies to work with streams.
+*/
+inline std::ostream& operator<< (std::ostream& os, LuaRef const& ref)
+{
+ ref.print (os);
+ return os;
+}
+
+//------------------------------------------------------------------------------
+
+// more C++-like cast syntax
+//
+template<class T>
+inline T LuaRef_cast(LuaRef const& lr)
+{
+ return lr.cast<T>();
+}
diff --git a/contrib/src/LuaBridge/detail/Namespace.h b/contrib/src/LuaBridge/detail/Namespace.h
new file mode 100644
index 0000000..ff22e6b
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/Namespace.h
@@ -0,0 +1,1136 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+/** Provides C++ to Lua registration capabilities.
+
+ This class is not instantiated directly, call `getGlobalNamespace` to start
+ the registration process.
+*/
+class Namespace
+{
+private:
+ Namespace& operator= (Namespace const& other);
+
+ lua_State* const L;
+ int mutable m_stackSize;
+
+private:
+ //============================================================================
+ /**
+ Error reporting.
+
+ VF: This function looks handy, why aren't we using it?
+ */
+#if 0
+ static int luaError (lua_State* L, std::string message)
+ {
+ assert (lua_isstring (L, lua_upvalueindex (1)));
+ std::string s;
+
+ // Get information on the caller's caller to format the message,
+ // so the error appears to originate from the Lua source.
+ lua_Debug ar;
+ int result = lua_getstack (L, 2, &ar);
+ if (result != 0)
+ {
+ lua_getinfo (L, "Sl", &ar);
+ s = ar.short_src;
+ if (ar.currentline != -1)
+ {
+ // poor mans int to string to avoid <strstrream>.
+ lua_pushnumber (L, ar.currentline);
+ s = s + ":" + lua_tostring (L, -1) + ": ";
+ lua_pop (L, 1);
+ }
+ }
+
+ s = s + message;
+
+ return luaL_error (L, s.c_str ());
+ }
+#endif
+
+ //----------------------------------------------------------------------------
+ /**
+ Pop the Lua stack.
+ */
+ void pop (int n) const
+ {
+ if (m_stackSize >= n && lua_gettop (L) >= n)
+ {
+ lua_pop (L, n);
+ m_stackSize -= n;
+ }
+ else
+ {
+ throw std::logic_error ("invalid stack");
+ }
+ }
+
+private:
+ /**
+ Factored base to reduce template instantiations.
+ */
+ class ClassBase
+ {
+ private:
+ ClassBase& operator= (ClassBase const& other);
+
+ protected:
+ friend class Namespace;
+
+ lua_State* const L;
+ int mutable m_stackSize;
+
+ protected:
+ //--------------------------------------------------------------------------
+ /**
+ __index metamethod for a class.
+
+ This implements member functions, data members, and property members.
+ Functions are stored in the metatable and const metatable. Data members
+ and property members are in the __propget table.
+
+ If the key is not found, the search proceeds up the hierarchy of base
+ classes.
+ */
+ static int indexMetaMethod (lua_State* L)
+ {
+ int result = 0;
+
+ assert (lua_isuserdata (L, 1)); // warn on security bypass
+ lua_getmetatable (L, 1); // get metatable for object
+ for (;;)
+ {
+ lua_pushvalue (L, 2); // push key arg2
+ lua_rawget (L, -2); // lookup key in metatable
+ if (lua_iscfunction (L, -1)) // ensure its a cfunction
+ {
+ lua_remove (L, -2); // remove metatable
+ result = 1;
+ break;
+ }
+ else if (lua_isnil (L, -1))
+ {
+ lua_pop (L, 1);
+ }
+ else
+ {
+ lua_pop (L, 2);
+ throw std::logic_error ("not a cfunction");
+ }
+
+ rawgetfield (L, -1, "__propget"); // get __propget table
+ if (lua_istable (L, -1)) // ensure it is a table
+ {
+ lua_pushvalue (L, 2); // push key arg2
+ lua_rawget (L, -2); // lookup key in __propget
+ lua_remove (L, -2); // remove __propget
+ if (lua_iscfunction (L, -1)) // ensure its a cfunction
+ {
+ lua_remove (L, -2); // remove metatable
+ lua_pushvalue (L, 1); // push class arg1
+ lua_call (L, 1, 1);
+ result = 1;
+ break;
+ }
+ else if (lua_isnil (L, -1))
+ {
+ lua_pop (L, 1);
+ }
+ else
+ {
+ lua_pop (L, 2);
+
+ // We only put cfunctions into __propget.
+ throw std::logic_error ("not a cfunction");
+ }
+ }
+ else
+ {
+ lua_pop (L, 2);
+
+ // __propget is missing, or not a table.
+ throw std::logic_error ("missing __propget table");
+ }
+
+ // Repeat the lookup in the __parent metafield,
+ // or return nil if the field doesn't exist.
+ rawgetfield (L, -1, "__parent");
+ if (lua_istable (L, -1))
+ {
+ // Remove metatable and repeat the search in __parent.
+ lua_remove (L, -2);
+ }
+ else if (lua_isnil (L, -1))
+ {
+ result = 1;
+ break;
+ }
+ else
+ {
+ lua_pop (L, 2);
+
+ throw std::logic_error ("__parent is not a table");
+ }
+ }
+
+ return result;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ __newindex metamethod for classes.
+
+ This supports writable variables and properties on class objects. The
+ corresponding object is passed in the first parameter to the set function.
+ */
+ static int newindexMetaMethod (lua_State* L)
+ {
+ int result = 0;
+
+ lua_getmetatable (L, 1);
+
+ for (;;)
+ {
+ // Check __propset
+ rawgetfield (L, -1, "__propset");
+ if (!lua_isnil (L, -1))
+ {
+ lua_pushvalue (L, 2);
+ lua_rawget (L, -2);
+ if (!lua_isnil (L, -1))
+ {
+ // found it, call the setFunction.
+ assert (lua_isfunction (L, -1));
+ lua_pushvalue (L, 1);
+ lua_pushvalue (L, 3);
+ lua_call (L, 2, 0);
+ result = 0;
+ break;
+ }
+ lua_pop (L, 1);
+ }
+ lua_pop (L, 1);
+
+ // Repeat the lookup in the __parent metafield.
+ rawgetfield (L, -1, "__parent");
+ if (lua_isnil (L, -1))
+ {
+ // Either the property or __parent must exist.
+ result = luaL_error (L,
+ "no member named '%s'", lua_tostring (L, 2));
+ }
+ lua_remove (L, -2);
+ }
+
+ return result;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Create the const table.
+ */
+ void createConstTable (char const* name)
+ {
+ lua_newtable (L);
+ lua_pushvalue (L, -1);
+ lua_setmetatable (L, -2);
+ lua_pushboolean (L, 1);
+ lua_rawsetp (L, -2, getIdentityKey ());
+ lua_pushstring (L, (std::string ("const ") + name).c_str ());
+ rawsetfield (L, -2, "__type");
+ lua_pushcfunction (L, &indexMetaMethod);
+ rawsetfield (L, -2, "__index");
+ lua_pushcfunction (L, &newindexMetaMethod);
+ rawsetfield (L, -2, "__newindex");
+ lua_newtable (L);
+ rawsetfield (L, -2, "__propget");
+
+ if (Security::hideMetatables ())
+ {
+ lua_pushnil (L);
+ rawsetfield (L, -2, "__metatable");
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Create the class table.
+
+ The Lua stack should have the const table on top.
+ */
+ void createClassTable (char const* name)
+ {
+ lua_newtable (L);
+ lua_pushvalue (L, -1);
+ lua_setmetatable (L, -2);
+ lua_pushboolean (L, 1);
+ lua_rawsetp (L, -2, getIdentityKey ());
+ lua_pushstring (L, name);
+ rawsetfield (L, -2, "__type");
+ lua_pushcfunction (L, &indexMetaMethod);
+ rawsetfield (L, -2, "__index");
+ lua_pushcfunction (L, &newindexMetaMethod);
+ rawsetfield (L, -2, "__newindex");
+ lua_newtable (L);
+ rawsetfield (L, -2, "__propget");
+ lua_newtable (L);
+ rawsetfield (L, -2, "__propset");
+
+ lua_pushvalue (L, -2);
+ rawsetfield (L, -2, "__const"); // point to const table
+
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -3, "__class"); // point const table to class table
+
+ if (Security::hideMetatables ())
+ {
+ lua_pushnil (L);
+ rawsetfield (L, -2, "__metatable");
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Create the static table.
+
+ The Lua stack should have:
+ -1 class table
+ -2 const table
+ -3 enclosing namespace
+ */
+ void createStaticTable (char const* name)
+ {
+ lua_newtable (L);
+ lua_newtable (L);
+ lua_pushvalue (L, -1);
+ lua_setmetatable (L, -3);
+ lua_insert (L, -2);
+ rawsetfield (L, -5, name);
+
+#if 0
+ lua_pushlightuserdata (L, this);
+ lua_pushcclosure (L, &tostringMetaMethod, 1);
+ rawsetfield (L, -2, "__tostring");
+#endif
+ lua_pushcfunction (L, &CFunc::indexMetaMethod);
+ rawsetfield (L, -2, "__index");
+ lua_pushcfunction (L, &CFunc::newindexMetaMethod);
+ rawsetfield (L, -2, "__newindex");
+ lua_newtable (L);
+ rawsetfield (L, -2, "__propget");
+ lua_newtable (L);
+ rawsetfield (L, -2, "__propset");
+
+ lua_pushvalue (L, -2);
+ rawsetfield (L, -2, "__class"); // point to class table
+
+ if (Security::hideMetatables ())
+ {
+ lua_pushnil (L);
+ rawsetfield (L, -2, "__metatable");
+ }
+ }
+
+ //==========================================================================
+ /**
+ lua_CFunction to construct a class object wrapped in a container.
+ */
+ template <class Params, class C>
+ static int ctorContainerProxy (lua_State* L)
+ {
+ typedef typename ContainerTraits <C>::Type T;
+ ArgList <Params, 2> args (L);
+ T* const p = Constructor <T, Params>::call (args);
+ UserdataSharedHelper <C, false>::push (L, p);
+ return 1;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ lua_CFunction to construct a class object in-place in the userdata.
+ */
+ template <class Params, class T>
+ static int ctorPlacementProxy (lua_State* L)
+ {
+ ArgList <Params, 2> args (L);
+ Constructor <T, Params>::call (UserdataValue <T>::place (L), args);
+ return 1;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Pop the Lua stack.
+ */
+ void pop (int n) const
+ {
+ if (m_stackSize >= n && lua_gettop (L) >= n)
+ {
+ lua_pop (L, n);
+ m_stackSize -= n;
+ }
+ else
+ {
+ throw std::logic_error ("invalid stack");
+ }
+ }
+
+ public:
+ //--------------------------------------------------------------------------
+ explicit ClassBase (lua_State* L_)
+ : L (L_)
+ , m_stackSize (0)
+ {
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Copy Constructor.
+ */
+ ClassBase (ClassBase const& other)
+ : L (other.L)
+ , m_stackSize (0)
+ {
+ m_stackSize = other.m_stackSize;
+ other.m_stackSize = 0;
+ }
+
+ ~ClassBase ()
+ {
+ pop (m_stackSize);
+ }
+ };
+
+ //============================================================================
+ //
+ // Class
+ //
+ //============================================================================
+ /**
+ Provides a class registration in a lua_State.
+
+ After contstruction the Lua stack holds these objects:
+ -1 static table
+ -2 class table
+ -3 const table
+ -4 (enclosing namespace)
+ */
+ template <class T>
+ class Class : public ClassBase
+ {
+ public:
+ //==========================================================================
+ /**
+ Register a new class or add to an existing class registration.
+ */
+ Class (char const* name, Namespace const* parent) : ClassBase (parent->L)
+ {
+ m_stackSize = parent->m_stackSize + 3;
+ parent->m_stackSize = 0;
+
+ assert (lua_istable (L, -1));
+ rawgetfield (L, -1, name);
+
+ if (lua_isnil (L, -1))
+ {
+ lua_pop (L, 1);
+
+ createConstTable (name);
+ lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
+ rawsetfield (L, -2, "__gc");
+
+ createClassTable (name);
+ lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
+ rawsetfield (L, -2, "__gc");
+
+ createStaticTable (name);
+
+ // Map T back to its tables.
+ lua_pushvalue (L, -1);
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
+ lua_pushvalue (L, -2);
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+ lua_pushvalue (L, -3);
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
+ }
+ else
+ {
+ rawgetfield (L, -1, "__class");
+ rawgetfield (L, -1, "__const");
+
+ // Reverse the top 3 stack elements
+ lua_insert (L, -3);
+ lua_insert (L, -2);
+ }
+ }
+
+ //==========================================================================
+ /**
+ Derive a new class.
+ */
+ Class (char const* name, Namespace const* parent, void const* const staticKey)
+ : ClassBase (parent->L)
+ {
+ m_stackSize = parent->m_stackSize + 3;
+ parent->m_stackSize = 0;
+
+ assert (lua_istable (L, -1));
+
+ createConstTable (name);
+ lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
+ rawsetfield (L, -2, "__gc");
+
+ createClassTable (name);
+ lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
+ rawsetfield (L, -2, "__gc");
+
+ createStaticTable (name);
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey);
+ assert (lua_istable (L, -1));
+ rawgetfield (L, -1, "__class");
+ assert (lua_istable (L, -1));
+ rawgetfield (L, -1, "__const");
+ assert (lua_istable (L, -1));
+
+ rawsetfield (L, -6, "__parent");
+ rawsetfield (L, -4, "__parent");
+ rawsetfield (L, -2, "__parent");
+
+ lua_pushvalue (L, -1);
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
+ lua_pushvalue (L, -2);
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+ lua_pushvalue (L, -3);
+ lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Continue registration in the enclosing namespace.
+ */
+ Namespace endClass ()
+ {
+ return Namespace (this);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a static data member.
+ */
+ template <class U>
+ Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true)
+ {
+ assert (lua_istable (L, -1));
+
+ rawgetfield (L, -1, "__propget");
+ assert (lua_istable (L, -1));
+ lua_pushlightuserdata (L, pu);
+ lua_pushcclosure (L, &CFunc::getVariable <U>, 1);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+
+ rawgetfield (L, -1, "__propset");
+ assert (lua_istable (L, -1));
+ if (isWritable)
+ {
+ lua_pushlightuserdata (L, pu);
+ lua_pushcclosure (L, &CFunc::setVariable <U>, 1);
+ }
+ else
+ {
+ lua_pushstring (L, name);
+ lua_pushcclosure (L, &CFunc::readOnlyError, 1);
+ }
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a static property member.
+
+ If the set function is null, the property is read-only.
+ */
+ template <class U>
+ Class <T>& addStaticProperty (char const* name, U (*get)(), void (*set)(U) = 0)
+ {
+ typedef U (*get_t)();
+ typedef void (*set_t)(U);
+
+ assert (lua_istable (L, -1));
+
+ rawgetfield (L, -1, "__propget");
+ assert (lua_istable (L, -1));
+ new (lua_newuserdata (L, sizeof (get))) get_t (get);
+ lua_pushcclosure (L, &CFunc::Call <U (*) (void)>::f, 1);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+
+ rawgetfield (L, -1, "__propset");
+ assert (lua_istable (L, -1));
+ if (set != 0)
+ {
+ new (lua_newuserdata (L, sizeof (set))) set_t (set);
+ lua_pushcclosure (L, &CFunc::Call <void (*) (U)>::f, 1);
+ }
+ else
+ {
+ lua_pushstring (L, name);
+ lua_pushcclosure (L, &CFunc::readOnlyError, 1);
+ }
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a static member function.
+ */
+ template <class FP>
+ Class <T>& addStaticFunction (char const* name, FP const fp)
+ {
+ new (lua_newuserdata (L, sizeof (fp))) FP (fp);
+ lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
+ rawsetfield (L, -2, name);
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a lua_CFunction.
+ */
+ Class <T>& addStaticCFunction (char const* name, int (*const fp)(lua_State*))
+ {
+ lua_pushcfunction (L, fp);
+ rawsetfield (L, -2, name);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a data member.
+ */
+ template <class U>
+ Class <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
+ {
+ typedef const U T::*mp_t;
+
+ // Add to __propget in class and const tables.
+ {
+ rawgetfield (L, -2, "__propget");
+ rawgetfield (L, -4, "__propget");
+ new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
+ lua_pushcclosure (L, &CFunc::getProperty <T,U>, 1);
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -4, name);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 2);
+ }
+
+ if (isWritable)
+ {
+ // Add to __propset in class table.
+ rawgetfield (L, -2, "__propset");
+ assert (lua_istable (L, -1));
+ new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
+ lua_pushcclosure (L, &CFunc::setProperty <T,U>, 1);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+ }
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a property member.
+ */
+ template <class TG, class TS>
+ Class <T>& addProperty (char const* name, TG (T::* get) () const, void (T::* set) (TS))
+ {
+ // Add to __propget in class and const tables.
+ {
+ rawgetfield (L, -2, "__propget");
+ rawgetfield (L, -4, "__propget");
+ typedef TG (T::*get_t) () const;
+ new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
+ lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -4, name);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 2);
+ }
+
+ {
+ // Add to __propset in class table.
+ rawgetfield (L, -2, "__propset");
+ assert (lua_istable (L, -1));
+ typedef void (T::* set_t) (TS);
+ new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
+ lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+ }
+
+ return *this;
+ }
+
+ // read-only
+ template <class TG>
+ Class <T>& addProperty (char const* name, TG (T::* get) () const)
+ {
+ // Add to __propget in class and const tables.
+ rawgetfield (L, -2, "__propget");
+ rawgetfield (L, -4, "__propget");
+ typedef TG (T::*get_t) () const;
+ new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
+ lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -4, name);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 2);
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a property member, by proxy.
+
+ When a class is closed for modification and does not provide (or cannot
+ provide) the function signatures necessary to implement get or set for
+ a property, this will allow non-member functions act as proxies.
+
+ Both the get and the set functions require a T const* and T* in the first
+ argument respectively.
+ */
+ template <class TG, class TS>
+ Class <T>& addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS))
+ {
+ // Add to __propget in class and const tables.
+ {
+ rawgetfield (L, -2, "__propget");
+ rawgetfield (L, -4, "__propget");
+ typedef TG (*get_t) (T const*);
+ new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
+ lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -4, name);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 2);
+ }
+
+ if (set != 0)
+ {
+ // Add to __propset in class table.
+ rawgetfield (L, -2, "__propset");
+ assert (lua_istable (L, -1));
+ typedef void (*set_t) (T*, TS);
+ new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
+ lua_pushcclosure (L, &CFunc::Call <set_t>::f, 1);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+ }
+
+ return *this;
+ }
+
+ // read-only
+ template <class TG, class TS>
+ Class <T>& addProperty (char const* name, TG (*get) (T const*))
+ {
+ // Add to __propget in class and const tables.
+ rawgetfield (L, -2, "__propget");
+ rawgetfield (L, -4, "__propget");
+ typedef TG (*get_t) (T const*);
+ new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
+ lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -4, name);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 2);
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a member function.
+ */
+ template <class MemFn>
+ Class <T>& addFunction (char const* name, MemFn mf)
+ {
+ CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a member lua_CFunction.
+ */
+ Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*))
+ {
+ typedef int (T::*MFP)(lua_State*);
+ assert (lua_istable (L, -1));
+ new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
+ lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1);
+ rawsetfield (L, -3, name); // class table
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a const member lua_CFunction.
+ */
+ Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*) const)
+ {
+ typedef int (T::*MFP)(lua_State*) const;
+ assert (lua_istable (L, -1));
+ new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
+ lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1);
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -5, name); // const table
+ rawsetfield (L, -3, name); // class table
+
+ return *this;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Add or replace a primary Constructor.
+
+ The primary Constructor is invoked when calling the class type table
+ like a function.
+
+ The template parameter should be a function pointer type that matches
+ the desired Constructor (since you can't take the address of a Constructor
+ and pass it as an argument).
+ */
+ template <class MemFn, class C>
+ Class <T>& addConstructor ()
+ {
+ lua_pushcclosure (L,
+ &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
+ rawsetfield(L, -2, "__call");
+
+ return *this;
+ }
+
+ template <class MemFn>
+ Class <T>& addConstructor ()
+ {
+ lua_pushcclosure (L,
+ &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
+ rawsetfield(L, -2, "__call");
+
+ return *this;
+ }
+ };
+
+private:
+ //----------------------------------------------------------------------------
+ /**
+ Open the global namespace for registrations.
+ */
+ explicit Namespace (lua_State* L_)
+ : L (L_)
+ , m_stackSize (0)
+ {
+ lua_getglobal (L, "_G");
+ ++m_stackSize;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Open a namespace for registrations.
+
+ The namespace is created if it doesn't already exist.
+ The parent namespace is at the top of the Lua stack.
+ */
+ Namespace (char const* name, Namespace const* parent)
+ : L (parent->L)
+ , m_stackSize (0)
+ {
+ m_stackSize = parent->m_stackSize + 1;
+ parent->m_stackSize = 0;
+
+ assert (lua_istable (L, -1));
+ rawgetfield (L, -1, name);
+ if (lua_isnil (L, -1))
+ {
+ lua_pop (L, 1);
+
+ lua_newtable (L);
+ lua_pushvalue (L, -1);
+ lua_setmetatable (L, -2);
+ lua_pushcfunction (L, &CFunc::indexMetaMethod);
+ rawsetfield (L, -2, "__index");
+ lua_pushcfunction (L, &CFunc::newindexMetaMethod);
+ rawsetfield (L, -2, "__newindex");
+ lua_newtable (L);
+ rawsetfield (L, -2, "__propget");
+ lua_newtable (L);
+ rawsetfield (L, -2, "__propset");
+ lua_pushvalue (L, -1);
+ rawsetfield (L, -3, name);
+#if 0
+ lua_pushcfunction (L, &tostringMetaMethod);
+ rawsetfield (L, -2, "__tostring");
+#endif
+ }
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Creates a continued registration from a child namespace.
+ */
+ explicit Namespace (Namespace const* child)
+ : L (child->L)
+ , m_stackSize (0)
+ {
+ m_stackSize = child->m_stackSize - 1;
+ child->m_stackSize = 1;
+ child->pop (1);
+
+ // It is not necessary or valid to call
+ // endNamespace() for the global namespace!
+ //
+ assert (m_stackSize != 0);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Creates a continued registration from a child class.
+ */
+ explicit Namespace (ClassBase const* child)
+ : L (child->L)
+ , m_stackSize (0)
+ {
+ m_stackSize = child->m_stackSize - 3;
+ child->m_stackSize = 3;
+ child->pop (3);
+ }
+
+public:
+ //----------------------------------------------------------------------------
+ /**
+ Copy Constructor.
+
+ Ownership of the stack is transferred to the new object. This happens
+ when the compiler emits temporaries to hold these objects while chaining
+ registrations across namespaces.
+ */
+ Namespace (Namespace const& other) : L (other.L)
+ {
+ m_stackSize = other.m_stackSize;
+ other.m_stackSize = 0;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Closes this namespace registration.
+ */
+ ~Namespace ()
+ {
+ pop (m_stackSize);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Open the global namespace.
+ */
+ static Namespace getGlobalNamespace (lua_State* L)
+ {
+ return Namespace (L);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Open a new or existing namespace for registrations.
+ */
+ Namespace beginNamespace (char const* name)
+ {
+ return Namespace (name, this);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Continue namespace registration in the parent.
+
+ Do not use this on the global namespace.
+ */
+ Namespace endNamespace ()
+ {
+ return Namespace (this);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a variable.
+ */
+ template <class T>
+ Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
+ {
+ assert (lua_istable (L, -1));
+
+ rawgetfield (L, -1, "__propget");
+ assert (lua_istable (L, -1));
+ lua_pushlightuserdata (L, pt);
+ lua_pushcclosure (L, &CFunc::getVariable <T>, 1);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+
+ rawgetfield (L, -1, "__propset");
+ assert (lua_istable (L, -1));
+ if (isWritable)
+ {
+ lua_pushlightuserdata (L, pt);
+ lua_pushcclosure (L, &CFunc::setVariable <T>, 1);
+ }
+ else
+ {
+ lua_pushstring (L, name);
+ lua_pushcclosure (L, &CFunc::readOnlyError, 1);
+ }
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a property.
+
+ If the set function is omitted or null, the property is read-only.
+ */
+ template <class TG, class TS>
+ Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0)
+ {
+ assert (lua_istable (L, -1));
+
+ rawgetfield (L, -1, "__propget");
+ assert (lua_istable (L, -1));
+ typedef TG (*get_t) ();
+ new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
+ lua_pushcclosure (L, &CFunc::Call <TG (*) (void)>::f, 1);
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+
+ rawgetfield (L, -1, "__propset");
+ assert (lua_istable (L, -1));
+ if (set != 0)
+ {
+ typedef void (*set_t) (TS);
+ new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
+ lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
+ }
+ else
+ {
+ lua_pushstring (L, name);
+ lua_pushcclosure (L, &CFunc::readOnlyError, 1);
+ }
+ rawsetfield (L, -2, name);
+ lua_pop (L, 1);
+
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a free function.
+ */
+ template <class FP>
+ Namespace& addFunction (char const* name, FP const fp)
+ {
+ assert (lua_istable (L, -1));
+
+ new (lua_newuserdata (L, sizeof (fp))) FP (fp);
+ lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
+ rawsetfield (L, -2, name);
+
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Add or replace a lua_CFunction.
+ */
+ Namespace& addCFunction (char const* name, int (*const fp)(lua_State*))
+ {
+ lua_pushcfunction (L, fp);
+ rawsetfield (L, -2, name);
+
+ return *this;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Open a new or existing class for registrations.
+ */
+ template <class T>
+ Class <T> beginClass (char const* name)
+ {
+ return Class <T> (name, this);
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ Derive a new class for registrations.
+
+ To continue registrations for the class later, use beginClass().
+ Do not call deriveClass() again.
+ */
+ template <class T, class U>
+ Class <T> deriveClass (char const* name)
+ {
+ return Class <T> (name, this, ClassInfo <U>::getStaticKey ());
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Retrieve the global namespace.
+
+ It is recommended to put your namespace inside the global namespace, and
+ then add your classes and functions to it, rather than adding many classes
+ and functions directly to the global namespace.
+*/
+inline Namespace getGlobalNamespace (lua_State* L)
+{
+ return Namespace::getGlobalNamespace (L);
+}
diff --git a/contrib/src/LuaBridge/detail/Stack.h b/contrib/src/LuaBridge/detail/Stack.h
new file mode 100644
index 0000000..d10fa8a
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/Stack.h
@@ -0,0 +1,469 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+//------------------------------------------------------------------------------
+/**
+ Receive the lua_State* as an argument.
+*/
+template <>
+struct Stack <lua_State*>
+{
+ static lua_State* get (lua_State* L, int)
+ {
+ return L;
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Push a lua_CFunction.
+*/
+template <>
+struct Stack <lua_CFunction>
+{
+ static void push (lua_State* L, lua_CFunction f)
+ {
+ lua_pushcfunction (L, f);
+ }
+
+ static lua_CFunction get (lua_State* L, int index)
+ {
+ return lua_tocfunction (L, index);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `int`.
+*/
+template <>
+struct Stack <int>
+{
+ static inline void push (lua_State* L, int value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static inline int get (lua_State* L, int index)
+ {
+ return static_cast <int> (luaL_checkinteger (L, index));
+ }
+};
+
+template <>
+struct Stack <int const&>
+{
+ static inline void push (lua_State* L, int value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline int get (lua_State* L, int index)
+ {
+ return static_cast <int > (luaL_checknumber (L, index));
+ }
+};
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `unsigned int`.
+*/
+template <>
+struct Stack <unsigned int>
+{
+ static inline void push (lua_State* L, unsigned int value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static inline unsigned int get (lua_State* L, int index)
+ {
+ return static_cast <unsigned int> (luaL_checkinteger (L, index));
+ }
+};
+
+template <>
+struct Stack <unsigned int const&>
+{
+ static inline void push (lua_State* L, unsigned int value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline unsigned int get (lua_State* L, int index)
+ {
+ return static_cast <unsigned int > (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `unsigned char`.
+*/
+template <>
+struct Stack <unsigned char>
+{
+ static inline void push (lua_State* L, unsigned char value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static inline unsigned char get (lua_State* L, int index)
+ {
+ return static_cast <unsigned char> (luaL_checkinteger (L, index));
+ }
+};
+
+template <>
+struct Stack <unsigned char const&>
+{
+ static inline void push (lua_State* L, unsigned char value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline unsigned char get (lua_State* L, int index)
+ {
+ return static_cast <unsigned char> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `short`.
+*/
+template <>
+struct Stack <short>
+{
+ static inline void push (lua_State* L, short value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static inline short get (lua_State* L, int index)
+ {
+ return static_cast <short> (luaL_checkinteger (L, index));
+ }
+};
+
+template <>
+struct Stack <short const&>
+{
+ static inline void push (lua_State* L, short value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline short get (lua_State* L, int index)
+ {
+ return static_cast <short> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `unsigned short`.
+*/
+template <>
+struct Stack <unsigned short>
+{
+ static inline void push (lua_State* L, unsigned short value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static inline unsigned short get (lua_State* L, int index)
+ {
+ return static_cast <unsigned short> (luaL_checkinteger (L, index));
+ }
+};
+
+template <>
+struct Stack <unsigned short const&>
+{
+ static inline void push (lua_State* L, unsigned short value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline unsigned short get (lua_State* L, int index)
+ {
+ return static_cast <unsigned short> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `long`.
+*/
+template <>
+struct Stack <long>
+{
+ static inline void push (lua_State* L, long value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static inline long get (lua_State* L, int index)
+ {
+ return static_cast <long> (luaL_checkinteger (L, index));
+ }
+};
+
+template <>
+struct Stack <long const&>
+{
+ static inline void push (lua_State* L, long value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline long get (lua_State* L, int index)
+ {
+ return static_cast <long> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `unsigned long`.
+*/
+template <>
+struct Stack <unsigned long>
+{
+ static inline void push (lua_State* L, unsigned long value)
+ {
+ lua_pushinteger (L, static_cast <lua_Integer> (value));
+ }
+
+ static inline unsigned long get (lua_State* L, int index)
+ {
+ return static_cast <unsigned long> (luaL_checkinteger (L, index));
+ }
+};
+
+template <>
+struct Stack <unsigned long const&>
+{
+ static inline void push (lua_State* L, unsigned long value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline unsigned long get (lua_State* L, int index)
+ {
+ return static_cast <unsigned long> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `float`.
+*/
+template <>
+struct Stack <float>
+{
+ static inline void push (lua_State* L, float value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline float get (lua_State* L, int index)
+ {
+ return static_cast <float> (luaL_checknumber (L, index));
+ }
+};
+
+template <>
+struct Stack <float const&>
+{
+ static inline void push (lua_State* L, float value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline float get (lua_State* L, int index)
+ {
+ return static_cast <float> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `double`.
+*/
+template <> struct Stack <double>
+{
+ static inline void push (lua_State* L, double value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline double get (lua_State* L, int index)
+ {
+ return static_cast <double> (luaL_checknumber (L, index));
+ }
+};
+
+template <> struct Stack <double const&>
+{
+ static inline void push (lua_State* L, double value)
+ {
+ lua_pushnumber (L, static_cast <lua_Number> (value));
+ }
+
+ static inline double get (lua_State* L, int index)
+ {
+ return static_cast <double> (luaL_checknumber (L, index));
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `bool`.
+*/
+template <>
+struct Stack <bool> {
+ static inline void push (lua_State* L, bool value)
+ {
+ lua_pushboolean (L, value ? 1 : 0);
+ }
+
+ static inline bool get (lua_State* L, int index)
+ {
+ return lua_toboolean (L, index) ? true : false;
+ }
+};
+
+template <>
+struct Stack <bool const&> {
+ static inline void push (lua_State* L, bool value)
+ {
+ lua_pushboolean (L, value ? 1 : 0);
+ }
+
+ static inline bool get (lua_State* L, int index)
+ {
+ return lua_toboolean (L, index) ? true : false;
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `char`.
+*/
+template <>
+struct Stack <char>
+{
+ static inline void push (lua_State* L, char value)
+ {
+ char str [2] = { value, 0 };
+ lua_pushstring (L, str);
+ }
+
+ static inline char get (lua_State* L, int index)
+ {
+ return luaL_checkstring (L, index) [0];
+ }
+};
+
+template <>
+struct Stack <char const&>
+{
+ static inline void push (lua_State* L, char value)
+ {
+ char str [2] = { value, 0 };
+ lua_pushstring (L, str);
+ }
+
+ static inline char get (lua_State* L, int index)
+ {
+ return luaL_checkstring (L, index) [0];
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `float`.
+*/
+template <>
+struct Stack <char const*>
+{
+ static inline void push (lua_State* L, char const* str)
+ {
+ if (str != 0)
+ lua_pushstring (L, str);
+ else
+ lua_pushnil (L);
+ }
+
+ static inline char const* get (lua_State* L, int index)
+ {
+ return lua_isnil (L, index) ? 0 : luaL_checkstring (L, index);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `std::string`.
+*/
+template <>
+struct Stack <std::string>
+{
+ static inline void push (lua_State* L, std::string const& str)
+ {
+ lua_pushlstring (L, str.c_str (), str.size());
+ }
+
+ static inline std::string get (lua_State* L, int index)
+ {
+ size_t len;
+ const char *str = luaL_checklstring(L, index, &len);
+ return std::string (str, len);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Stack specialization for `std::string const&`.
+*/
+template <>
+struct Stack <std::string const&>
+{
+ static inline void push (lua_State* L, std::string const& str)
+ {
+ lua_pushlstring (L, str.c_str(), str.size());
+ }
+
+ static inline std::string get (lua_State* L, int index)
+ {
+ size_t len;
+ const char *str = luaL_checklstring(L, index, &len);
+ return std::string (str, len);
+ }
+};
diff --git a/contrib/src/LuaBridge/detail/TypeList.h b/contrib/src/LuaBridge/detail/TypeList.h
new file mode 100644
index 0000000..21f850e
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/TypeList.h
@@ -0,0 +1,174 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+ Copyright 2007, Nathan Reed
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ This file incorporates work covered by the following copyright and
+ permission notice:
+
+ The Loki Library
+ Copyright (c) 2001 by Andrei Alexandrescu
+ This code accompanies the book:
+ Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+ Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+ Permission to use, copy, modify, distribute and sell this software for any
+ purpose is hereby granted without fee, provided that the above copyright
+ notice appear in all copies and that both that copyright notice and this
+ permission notice appear in supporting documentation.
+ The author or Addison-Welsey Longman make no representations about the
+ suitability of this software for any purpose. It is provided "as is"
+ without express or implied warranty.
+*/
+//==============================================================================
+
+/**
+ None type means void parameters or return value.
+*/
+typedef void None;
+
+template <typename Head, typename Tail = None>
+struct TypeList
+{
+};
+
+/**
+ A TypeList with actual values.
+*/
+template <typename List>
+struct TypeListValues
+{
+ static std::string const tostring (bool)
+ {
+ return "";
+ }
+};
+
+/**
+ TypeListValues recursive template definition.
+*/
+template <typename Head, typename Tail>
+struct TypeListValues <TypeList <Head, Tail> >
+{
+ Head hd;
+ TypeListValues <Tail> tl;
+
+ TypeListValues (Head hd_, TypeListValues <Tail> const& tl_)
+ : hd (hd_), tl (tl_)
+ {
+ }
+
+ static std::string const tostring (bool comma = false)
+ {
+ std::string s;
+
+ if (comma)
+ s = ", ";
+
+ s = s + typeid (Head).name ();
+
+ return s + TypeListValues <Tail>::tostring (true);
+ }
+};
+
+// Specializations of type/value list for head types that are references and
+// const-references. We need to handle these specially since we can't count
+// on the referenced object hanging around for the lifetime of the list.
+
+template <typename Head, typename Tail>
+struct TypeListValues <TypeList <Head&, Tail> >
+{
+ Head hd;
+ TypeListValues <Tail> tl;
+
+ TypeListValues (Head& hd_, TypeListValues <Tail> const& tl_)
+ : hd (hd_), tl (tl_)
+ {
+ }
+
+ static std::string const tostring (bool comma = false)
+ {
+ std::string s;
+
+ if (comma)
+ s = ", ";
+
+ s = s + typeid (Head).name () + "&";
+
+ return s + TypeListValues <Tail>::tostring (true);
+ }
+};
+
+template <typename Head, typename Tail>
+struct TypeListValues <TypeList <Head const&, Tail> >
+{
+ Head hd;
+ TypeListValues <Tail> tl;
+
+ TypeListValues (Head const& hd_, const TypeListValues <Tail>& tl_)
+ : hd (hd_), tl (tl_)
+ {
+ }
+
+ static std::string const tostring (bool comma = false)
+ {
+ std::string s;
+
+ if (comma)
+ s = ", ";
+
+ s = s + typeid (Head).name () + " const&";
+
+ return s + TypeListValues <Tail>::tostring (true);
+ }
+};
+
+//==============================================================================
+/**
+ Subclass of a TypeListValues constructable from the Lua stack.
+*/
+
+template <typename List, int Start = 1>
+struct ArgList
+{
+};
+
+template <int Start>
+struct ArgList <None, Start> : public TypeListValues <None>
+{
+ ArgList (lua_State*)
+ {
+ }
+};
+
+template <typename Head, typename Tail, int Start>
+struct ArgList <TypeList <Head, Tail>, Start>
+ : public TypeListValues <TypeList <Head, Tail> >
+{
+ ArgList (lua_State* L)
+ : TypeListValues <TypeList <Head, Tail> > (Stack <Head>::get (L, Start),
+ ArgList <Tail, Start + 1> (L))
+ {
+ }
+};
diff --git a/contrib/src/LuaBridge/detail/TypeTraits.h b/contrib/src/LuaBridge/detail/TypeTraits.h
new file mode 100644
index 0000000..5dd0771
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/TypeTraits.h
@@ -0,0 +1,125 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef LUABRIDGE_TYPEINFO_HEADER
+#define LUABRIDGE_TYPEINFO_HEADER
+
+//------------------------------------------------------------------------------
+/**
+ Container traits.
+
+ Unspecialized ContainerTraits has the isNotContainer typedef for SFINAE.
+ All user defined containers must supply an appropriate specialization for
+ ContinerTraits (without the typedef isNotContainer). The containers that
+ come with LuaBridge also come with the appropriate ContainerTraits
+ specialization. See the corresponding declaration for details.
+
+ A specialization of ContainerTraits for some generic type ContainerType
+ looks like this:
+
+ template <class T>
+ struct ContainerTraits <ContainerType <T> >
+ {
+ typedef typename T Type;
+
+ static T* get (ContainerType <T> const& c)
+ {
+ return c.get (); // Implementation-dependent on ContainerType
+ }
+ };
+*/
+template <class T>
+struct ContainerTraits
+{
+ typedef bool isNotContainer;
+};
+
+//------------------------------------------------------------------------------
+/**
+ Type traits.
+
+ Specializations return information about a type.
+*/
+struct TypeTraits
+{
+ /** Determine if type T is a container.
+
+ To be considered a container, there must be a specialization of
+ ContainerTraits with the required fields.
+ */
+ template <typename T>
+ class isContainer
+ {
+ private:
+ typedef char yes[1]; // sizeof (yes) == 1
+ typedef char no [2]; // sizeof (no) == 2
+
+ template <typename C>
+ static no& test (typename C::isNotContainer*);
+
+ template <typename>
+ static yes& test (...);
+
+ public:
+ static const bool value = sizeof (test <ContainerTraits <T> >(0)) == sizeof (yes);
+ };
+
+ /** Determine if T is const qualified.
+ */
+ /** @{ */
+ template <class T>
+ struct isConst
+ {
+ static bool const value = false;
+ };
+
+ template <class T>
+ struct isConst <T const>
+ {
+ static bool const value = true;
+ };
+ /** @} */
+
+ /** Remove the const qualifier from T.
+ */
+ /** @{ */
+ template <class T>
+ struct removeConst
+ {
+ typedef T Type;
+ };
+
+ template <class T>
+ struct removeConst <T const>
+ {
+ typedef T Type;
+ };
+ /**@}*/
+};
+
+#endif
diff --git a/contrib/src/LuaBridge/detail/Userdata.h b/contrib/src/LuaBridge/detail/Userdata.h
new file mode 100644
index 0000000..19451bd
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/Userdata.h
@@ -0,0 +1,817 @@
+//------------------------------------------------------------------------------
+/*
+ https://github.com/vinniefalco/LuaBridge
+
+ Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
+
+ License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+//==============================================================================
+
+//==============================================================================
+/**
+ Return the identity pointer for our lightuserdata tokens.
+
+ LuaBridge metatables are tagged with a security "token." The token is a
+ lightuserdata created from the identity pointer, used as a key in the
+ metatable. The value is a boolean = true, although any value could have been
+ used.
+
+ Because of Lua's dynamic typing and our improvised system of imposing C++
+ class structure, there is the possibility that executing scripts may
+ knowingly or unknowingly cause invalid data to get passed to the C functions
+ created by LuaBridge. In particular, our security model addresses the
+ following:
+
+ Notes:
+ 1. Scripts cannot create a userdata (ignoring the debug lib).
+ 2. Scripts cannot create a lightuserdata (ignoring the debug lib).
+ 3. Scripts cannot set the metatable on a userdata.
+ 4. Our identity key is a unique pointer in the process.
+ 5. Our metatables have a lightuserdata identity key / value pair.
+ 6. Our metatables have "__metatable" set to a boolean = false.
+ 7. Our lightuserdata is unique.
+*/
+inline void* getIdentityKey ()
+{
+ static char value;
+ return &value;
+}
+
+/**
+ Interface to a class pointer retrievable from a userdata.
+*/
+class Userdata
+{
+protected:
+ void* m_p; // subclasses must set this
+
+ //--------------------------------------------------------------------------
+ /**
+ Get an untyped pointer to the contained class.
+ */
+ inline void* const getPointer ()
+ {
+ return m_p;
+ }
+
+private:
+ //--------------------------------------------------------------------------
+ /**
+ Validate and retrieve a Userdata on the stack.
+
+ The Userdata must exactly match the corresponding class table or
+ const table, or else a Lua error is raised. This is used for the
+ __gc metamethod.
+ */
+ static Userdata* getExactClass (lua_State* L,
+ int narg,
+ void const* classKey)
+ {
+ Userdata* ud = 0;
+ int const index = lua_absindex (L, narg);
+
+ bool mismatch = false;
+ char const* got = 0;
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX, classKey);
+ assert (lua_istable (L, -1));
+
+ // Make sure we have a userdata.
+ if (!lua_isuserdata (L, index))
+ mismatch = true;
+
+ // Make sure it's metatable is ours.
+ if (!mismatch)
+ {
+ lua_getmetatable (L, index);
+ lua_rawgetp (L, -1, getIdentityKey ());
+ if (lua_isboolean (L, -1))
+ {
+ lua_pop (L, 1);
+ }
+ else
+ {
+ lua_pop (L, 2);
+ mismatch = true;
+ }
+ }
+
+ if (!mismatch)
+ {
+ if (lua_rawequal (L, -1, -2))
+ {
+ // Matches class table.
+ lua_pop (L, 2);
+ ud = static_cast <Userdata*> (lua_touserdata (L, index));
+ }
+ else
+ {
+ rawgetfield (L, -2, "__const");
+ if (lua_rawequal (L, -1, -2))
+ {
+ // Matches const table
+ lua_pop (L, 3);
+ ud = static_cast <Userdata*> (lua_touserdata (L, index));
+ }
+ else
+ {
+ // Mismatch, but its one of ours so get a type name.
+ rawgetfield (L, -2, "__type");
+ lua_insert (L, -4);
+ lua_pop (L, 2);
+ got = lua_tostring (L, -2);
+ mismatch = true;
+ }
+ }
+ }
+
+ if (mismatch)
+ {
+ rawgetfield (L, -1, "__type");
+ assert (lua_type (L, -1) == LUA_TSTRING);
+ char const* const expected = lua_tostring (L, -1);
+
+ if (got == 0)
+ got = lua_typename (L, lua_type (L, index));
+
+ char const* const msg = lua_pushfstring (
+ L, "%s expected, got %s", expected, got);
+
+ if (narg > 0)
+ luaL_argerror (L, narg, msg);
+ else
+ lua_error (L);
+ }
+
+ return ud;
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Validate and retrieve a Userdata on the stack.
+
+ The Userdata must be derived from or the same as the given base class,
+ identified by the key. If canBeConst is false, generates an error if
+ the resulting Userdata represents to a const object. We do the type check
+ first so that the error message is informative.
+ */
+ static Userdata* getClass (lua_State* L,
+ int index,
+ void const* baseClassKey,
+ bool canBeConst)
+ {
+ assert (index > 0);
+ Userdata* ud = 0;
+
+ bool mismatch = false;
+ char const* got = 0;
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX, baseClassKey);
+ assert (lua_istable (L, -1));
+
+ // Make sure we have a userdata.
+ if (lua_isuserdata (L, index))
+ {
+ // Make sure it's metatable is ours.
+ lua_getmetatable (L, index);
+ lua_rawgetp (L, -1, getIdentityKey ());
+ if (lua_isboolean (L, -1))
+ {
+ lua_pop (L, 1);
+
+ // If __const is present, object is NOT const.
+ rawgetfield (L, -1, "__const");
+ assert (lua_istable (L, -1) || lua_isnil (L, -1));
+ bool const isConst = lua_isnil (L, -1);
+ lua_pop (L, 1);
+
+ // Replace the class table with the const table if needed.
+ if (isConst)
+ {
+ rawgetfield (L, -2, "__const");
+ assert (lua_istable (L, -1));
+ lua_replace (L, -3);
+ }
+
+ for (;;)
+ {
+ if (lua_rawequal (L, -1, -2))
+ {
+ lua_pop (L, 2);
+
+ // Match, now check const-ness.
+ if (isConst && !canBeConst)
+ {
+ luaL_argerror (L, index, "cannot be const");
+ }
+ else
+ {
+ ud = static_cast <Userdata*> (lua_touserdata (L, index));
+ break;
+ }
+ }
+ else
+ {
+ // Replace current metatable with it's base class.
+ rawgetfield (L, -1, "__parent");
+/*
+ud
+class metatable
+ud metatable
+ud __parent (nil)
+*/
+
+ if (lua_isnil (L, -1))
+ {
+ lua_remove (L, -1);
+ // Mismatch, but its one of ours so get a type name.
+ rawgetfield (L, -1, "__type");
+ lua_insert (L, -3);
+ lua_pop (L, 1);
+ got = lua_tostring (L, -2);
+ mismatch = true;
+ break;
+ }
+ else
+ {
+ lua_remove (L, -2);
+ }
+ }
+ }
+ }
+ else
+ {
+ lua_pop (L, 2);
+ mismatch = true;
+ }
+ }
+ else
+ {
+ mismatch = true;
+ }
+
+ if (mismatch)
+ {
+ assert (lua_type (L, -1) == LUA_TTABLE);
+ rawgetfield (L, -1, "__type");
+ assert (lua_type (L, -1) == LUA_TSTRING);
+ char const* const expected = lua_tostring (L, -1);
+
+ if (got == 0)
+ got = lua_typename (L, lua_type (L, index));
+
+ char const* const msg = lua_pushfstring (
+ L, "%s expected, got %s", expected, got);
+
+ luaL_argerror (L, index, msg);
+ }
+
+ return ud;
+ }
+
+public:
+ virtual ~Userdata () { }
+
+ //--------------------------------------------------------------------------
+ /**
+ Returns the Userdata* if the class on the Lua stack matches.
+
+ If the class does not match, a Lua error is raised.
+ */
+ template <class T>
+ static inline Userdata* getExact (lua_State* L, int index)
+ {
+ return getExactClass (L, index, ClassInfo <T>::getClassKey ());
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ Get a pointer to the class from the Lua stack.
+
+ If the object is not the class or a subclass, or it violates the
+ const-ness, a Lua error is raised.
+ */
+ template <class T>
+ static inline T* get (lua_State* L, int index, bool canBeConst)
+ {
+ if (lua_isnil (L, index))
+ return 0;
+ else
+ return static_cast <T*> (getClass (L, index,
+ ClassInfo <T>::getClassKey (), canBeConst)->getPointer ());
+ }
+};
+
+//----------------------------------------------------------------------------
+/**
+ Wraps a class object stored in a Lua userdata.
+
+ The lifetime of the object is managed by Lua. The object is constructed
+ inside the userdata using placement new.
+*/
+template <class T>
+class UserdataValue : public Userdata
+{
+private:
+ UserdataValue <T> (UserdataValue <T> const&);
+ UserdataValue <T> operator= (UserdataValue <T> const&);
+
+ char m_storage [sizeof (T)];
+
+ inline T* getObject ()
+ {
+ // If this fails to compile it means you forgot to provide
+ // a Container specialization for your container!
+ //
+ return reinterpret_cast <T*> (&m_storage [0]);
+ }
+
+private:
+ /**
+ Used for placement construction.
+ */
+ UserdataValue ()
+ {
+ m_p = getObject ();
+ }
+
+ ~UserdataValue ()
+ {
+ getObject ()->~T ();
+ }
+
+public:
+ /**
+ Push a T via placement new.
+
+ The caller is responsible for calling placement new using the
+ returned uninitialized storage.
+ */
+ static void* place (lua_State* const L)
+ {
+ UserdataValue <T>* const ud = new (
+ lua_newuserdata (L, sizeof (UserdataValue <T>))) UserdataValue <T> ();
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+ // If this goes off it means you forgot to register the class!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ return ud->getPointer ();
+ }
+
+ /**
+ Push T via copy construction from U.
+ */
+ template <class U>
+ static inline void push (lua_State* const L, U const& u)
+ {
+ new (place (L)) U (u);
+ }
+};
+
+//----------------------------------------------------------------------------
+/**
+ Wraps a pointer to a class object inside a Lua userdata.
+
+ The lifetime of the object is managed by C++.
+*/
+class UserdataPtr : public Userdata
+{
+private:
+ UserdataPtr (UserdataPtr const&);
+ UserdataPtr operator= (UserdataPtr const&);
+
+private:
+ /** Push non-const pointer to object using metatable key.
+ */
+ static void push (lua_State* L, void* const p, void const* const key)
+ {
+ if (p)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (p);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, key);
+ // If this goes off it means you forgot to register the class!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+
+ /** Push const pointer to object using metatable key.
+ */
+ static void push (lua_State* L, void const* const p, void const* const key)
+ {
+ if (p)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataPtr)))
+ UserdataPtr (const_cast <void*> (p));
+ lua_rawgetp (L, LUA_REGISTRYINDEX, key);
+ // If this goes off it means you forgot to register the class!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+
+ explicit UserdataPtr (void* const p)
+ {
+ m_p = p;
+
+ // Can't construct with a null pointer!
+ //
+ assert (m_p != 0);
+ }
+
+public:
+ /** Push non-const pointer to object.
+ */
+ template <class T>
+ static inline void push (lua_State* const L, T* const p)
+ {
+ if (p)
+ push (L, p, ClassInfo <T>::getClassKey ());
+ else
+ lua_pushnil (L);
+ }
+
+ /** Push const pointer to object.
+ */
+ template <class T>
+ static inline void push (lua_State* const L, T const* const p)
+ {
+ if (p)
+ push (L, p, ClassInfo <T>::getConstKey ());
+ else
+ lua_pushnil (L);
+ }
+};
+
+//============================================================================
+/**
+ Wraps a container thet references a class object.
+
+ The template argument C is the container type, ContainerTraits must be
+ specialized on C or else a compile error will result.
+*/
+template <class C>
+class UserdataShared : public Userdata
+{
+private:
+ UserdataShared (UserdataShared <C> const&);
+ UserdataShared <C>& operator= (UserdataShared <C> const&);
+
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ C m_c;
+
+private:
+ ~UserdataShared ()
+ {
+ }
+
+public:
+ /**
+ Construct from a container to the class or a derived class.
+ */
+ template <class U>
+ explicit UserdataShared (U const& u) : m_c (u)
+ {
+ m_p = const_cast <void*> (reinterpret_cast <void const*> (
+ (ContainerTraits <C>::get (m_c))));
+ }
+
+ /**
+ Construct from a pointer to the class or a derived class.
+ */
+ template <class U>
+ explicit UserdataShared (U* u) : m_c (u)
+ {
+ m_p = const_cast <void*> (reinterpret_cast <void const*> (
+ (ContainerTraits <C>::get (m_c))));
+ }
+};
+
+//----------------------------------------------------------------------------
+//
+// SFINAE helpers.
+//
+
+// non-const objects
+template <class C, bool makeObjectConst>
+struct UserdataSharedHelper
+{
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ static void push (lua_State* L, C const& c)
+ {
+ if (ContainerTraits <C>::get (c) != 0)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+ // If this goes off it means the class T is unregistered!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+
+ static void push (lua_State* L, T* const t)
+ {
+ if (t)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+ // If this goes off it means the class T is unregistered!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+};
+
+// const objects
+template <class C>
+struct UserdataSharedHelper <C, true>
+{
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ static void push (lua_State* L, C const& c)
+ {
+ if (ContainerTraits <C>::get (c) != 0)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
+ // If this goes off it means the class T is unregistered!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+
+ static void push (lua_State* L, T* const t)
+ {
+ if (t)
+ {
+ new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
+ lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
+ // If this goes off it means the class T is unregistered!
+ assert (lua_istable (L, -1));
+ lua_setmetatable (L, -2);
+ }
+ else
+ {
+ lua_pushnil (L);
+ }
+ }
+};
+
+/**
+ Pass by container.
+
+ The container controls the object lifetime. Typically this will be a
+ lifetime shared by C++ and Lua using a reference count. Because of type
+ erasure, containers like std::shared_ptr will not work. Containers must
+ either be of the intrusive variety, or in the style of the RefCountedPtr
+ type provided by LuaBridge (that uses a global hash table).
+*/
+template <class C, bool byContainer>
+struct StackHelper
+{
+ static inline void push (lua_State* L, C const& c)
+ {
+ UserdataSharedHelper <C,
+ TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c);
+ }
+
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ static inline C get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, true);
+ }
+};
+
+/**
+ Pass by value.
+
+ Lifetime is managed by Lua. A C++ function which accesses a pointer or
+ reference to an object outside the activation record in which it was
+ retrieved may result in undefined behavior if Lua garbage collected it.
+*/
+template <class T>
+struct StackHelper <T, false>
+{
+ static inline void push (lua_State* L, T const& t)
+ {
+ UserdataValue <T>::push (L, t);
+ }
+
+ static inline T const& get (lua_State* L, int index)
+ {
+ return *Userdata::get <T> (L, index, true);
+ }
+};
+
+//==============================================================================
+
+/**
+ Lua stack conversions for class objects passed by value.
+*/
+template <class T>
+struct Stack
+{
+public:
+ static inline void push (lua_State* L, T const& t)
+ {
+ StackHelper <T,
+ TypeTraits::isContainer <T>::value>::push (L, t);
+ }
+
+ static inline T get (lua_State* L, int index)
+ {
+ return StackHelper <T,
+ TypeTraits::isContainer <T>::value>::get (L, index);
+ }
+};
+
+//------------------------------------------------------------------------------
+/**
+ Lua stack conversions for pointers and references to class objects.
+
+ Lifetime is managed by C++. Lua code which remembers a reference to the
+ value may result in undefined behavior if C++ destroys the object. The
+ handling of the const and volatile qualifiers happens in UserdataPtr.
+*/
+
+// pointer
+template <class T>
+struct Stack <T*>
+{
+ static inline void push (lua_State* L, T* const p)
+ {
+ UserdataPtr::push (L, p);
+ }
+
+ static inline T* const get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, false);
+ }
+};
+
+// Strips the const off the right side of *
+template <class T>
+struct Stack <T* const>
+{
+ static inline void push (lua_State* L, T* const p)
+ {
+ UserdataPtr::push (L, p);
+ }
+
+ static inline T* const get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, false);
+ }
+};
+
+// pointer to const
+template <class T>
+struct Stack <T const*>
+{
+ static inline void push (lua_State* L, T const* const p)
+ {
+ UserdataPtr::push (L, p);
+ }
+
+ static inline T const* const get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, true);
+ }
+};
+
+// Strips the const off the right side of *
+template <class T>
+struct Stack <T const* const>
+{
+ static inline void push (lua_State* L, T const* const p)
+ {
+ UserdataPtr::push (L, p);
+ }
+
+ static inline T const* const get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, true);
+ }
+};
+
+// reference
+template <class T>
+struct Stack <T&>
+{
+ static inline void push (lua_State* L, T& t)
+ {
+ UserdataPtr::push (L, &t);
+ }
+
+ static T& get (lua_State* L, int index)
+ {
+ T* const t = Userdata::get <T> (L, index, false);
+ if (!t)
+ luaL_error (L, "nil passed to reference");
+ return *t;
+ }
+};
+
+template <class C, bool byContainer>
+struct RefStackHelper
+{
+ typedef C return_type;
+
+ static inline void push (lua_State* L, C const& t)
+ {
+ UserdataSharedHelper <C,
+ TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t);
+ }
+
+ typedef typename TypeTraits::removeConst <
+ typename ContainerTraits <C>::Type>::Type T;
+
+ static return_type get (lua_State* L, int index)
+ {
+ return Userdata::get <T> (L, index, true);
+ }
+};
+
+template <class T>
+struct RefStackHelper <T, false>
+{
+ typedef T const& return_type;
+
+ static inline void push (lua_State* L, T const& t)
+ {
+ UserdataPtr::push (L, &t);
+ }
+
+ static return_type get (lua_State* L, int index)
+ {
+ T const* const t = Userdata::get <T> (L, index, true);
+
+ if (!t)
+ luaL_error (L, "nil passed to reference");
+ return *t;
+ }
+
+};
+
+// reference to const
+template <class T>
+struct Stack <T const&>
+{
+ typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> helper_t;
+
+ static inline void push (lua_State* L, T const& t)
+ {
+ helper_t::push (L, t);
+ }
+
+ static typename helper_t::return_type get (lua_State* L, int index)
+ {
+ return helper_t::get (L, index);
+ }
+};
diff --git a/contrib/src/LuaBridge/detail/dump.h b/contrib/src/LuaBridge/detail/dump.h
new file mode 100644
index 0000000..c066803
--- /dev/null
+++ b/contrib/src/LuaBridge/detail/dump.h
@@ -0,0 +1,28 @@
+#include <sstream>
+#include <string>
+
+std::string dumpLuaState(lua_State *L) {
+ std::stringstream ostr;
+ int i;
+ int top = lua_gettop(L);
+ ostr << "top=" << top << ":\n";
+ for (i = 1; i <= top; ++i) {
+ int t = lua_type(L, i);
+ switch(t) {
+ case LUA_TSTRING:
+ ostr << " " << i << ": '" << lua_tostring(L, i) << "'\n";
+ break;
+ case LUA_TBOOLEAN:
+ ostr << " " << i << ": " <<
+ (lua_toboolean(L, i) ? "true" : "false") << "\n";
+ break;
+ case LUA_TNUMBER:
+ ostr << " " << i << ": " << lua_tonumber(L, i) << "\n";
+ break;
+ default:
+ ostr << " " << i << ": TYPE=" << lua_typename(L, t) << "\n";
+ break;
+ }
+ }
+ return ostr.str();
+}
diff --git a/embedding/csharp/uSCXMLEmbedding.suo b/embedding/csharp/uSCXMLEmbedding.suo
index 3d75994..b9b13c0 100644
--- a/embedding/csharp/uSCXMLEmbedding.suo
+++ b/embedding/csharp/uSCXMLEmbedding.suo
Binary files differ
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index 0f3e8c9..62756fc 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -104,6 +104,10 @@
# include "uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h"
# endif
+# ifdef LUA_FOUND
+# include "uscxml/plugins/datamodel/lua/LuaDataModel.h"
+# endif
+
#include "uscxml/plugins/datamodel/xpath/XPathDataModel.h"
#include "uscxml/plugins/datamodel/promela/PromelaDataModel.h"
@@ -299,6 +303,13 @@ void Factory::registerPlugins() {
}
#endif
+#if (defined LUA_FOUND && defined BUILD_DM_LUA)
+ {
+ LuaDataModel* dataModel = new LuaDataModel();
+ registerDataModel(dataModel);
+ }
+#endif
+
#if (defined BUILD_DM_PROMELA)
{
PromelaDataModel* dataModel = new PromelaDataModel();
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index e6fc8fa..d010a8a 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -2250,8 +2250,8 @@ NodeSet<std::string> InterpreterImpl::getProperAncestors(const Arabica::DOM::Nod
if (iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "scxml")) // do not return scxml root itself - this is somewhat ill-defined
break;
if (!iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "parallel") &&
- !iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "state") &&
- !iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "scxml"))
+ !iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "state") &&
+ !iequals(TAGNAME(nodeElem), _nsInfo.xmlNSPrefix + "scxml"))
break;
if (node == s2)
break;
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index 20f89d2..e2ba95e 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -948,10 +948,10 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>&
if (isFinal(stateElem)) {
internalDoneSend(stateElem);
Node<std::string> parent = stateElem.getParentNode();
-
+
if (parent.getNodeType() == Node_base::ELEMENT_NODE &&
- parent.getParentNode().getNodeType() == Node_base::ELEMENT_NODE &&
- isParallel(Element<std::string>(parent.getParentNode()))) {
+ parent.getParentNode().getNodeType() == Node_base::ELEMENT_NODE &&
+ isParallel(Element<std::string>(parent.getParentNode()))) {
Element<std::string> grandParent = (Element<std::string>)parent.getParentNode();
Arabica::XPath::NodeSet<std::string> childs = getChildStates(grandParent);
diff --git a/src/uscxml/plugins/datamodel/CMakeLists.txt b/src/uscxml/plugins/datamodel/CMakeLists.txt
index 1b2a047..acf7344 100644
--- a/src/uscxml/plugins/datamodel/CMakeLists.txt
+++ b/src/uscxml/plugins/datamodel/CMakeLists.txt
@@ -79,6 +79,30 @@ file(GLOB NULL_DATAMODEL
list (APPEND USCXML_FILES ${NULL_DATAMODEL})
+# Lua datamodel
+
+if (BUILD_DM_LUA AND LUA_FOUND)
+ set(USCXML_DATAMODELS "lua ${USCXML_DATAMODELS}")
+ file(GLOB LUA_DATAMODEL
+ lua/*.cpp
+ lua/*.h
+ )
+ if (BUILD_AS_PLUGINS)
+ source_group("" FILES ${LUA_DATAMODEL})
+ add_library(datamodel_lua SHARED ${LUA_DATAMODEL} "../Plugins.cpp")
+ target_link_libraries(datamodel_lua
+ uscxml
+ ${LUA_LIBRARIES}
+ )
+ set_target_properties(datamodel_lua PROPERTIES FOLDER "Plugin DataModel")
+ set_target_properties(datamodel_lua PROPERTIES COMPILE_FLAGS "-DPLUMA_EXPORTS")
+ set_target_properties(datamodel_lua PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}/lib")
+ else()
+ list (APPEND USCXML_FILES ${LUA_DATAMODEL})
+ endif()
+endif()
+
+
# XPath datamodel
if (BUILD_DM_XPATH)
diff --git a/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp
new file mode 100644
index 0000000..6fb0369
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/lua/LuaDataModel.cpp
@@ -0,0 +1,199 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include <boost/algorithm/string.hpp>
+
+#include "uscxml/Common.h"
+#include "LuaDataModel.h"
+#include "LuaBridge.h"
+#include "uscxml/DOMUtils.h"
+
+#include "uscxml/Message.h"
+#include <glog/logging.h>
+
+#ifdef BUILD_AS_PLUGINS
+#include <Pluma/Connector.hpp>
+#endif
+
+namespace uscxml {
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_CONNECTOR
+bool pluginConnect(pluma::Host& host) {
+ host.add( new LuaDataModelProvider() );
+ return true;
+}
+#endif
+
+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*>();
+
+ int stackSize = lua_gettop(l);
+ for (int i = 0; i < stackSize; i++) {
+ if (!lua_isstring(l, -1 - i))
+ continue;
+ std::string stateName = lua_tostring(l, -1 - i);
+ if (interpreter->isInState(stateName))
+ continue;
+ lua_pushboolean(l, 0);
+ return 1;
+ }
+ lua_pushboolean(l, 1);
+ return 1;
+}
+
+
+boost::shared_ptr<DataModelImpl> LuaDataModel::create(InterpreterImpl* interpreter) {
+ boost::shared_ptr<LuaDataModel> dm = boost::shared_ptr<LuaDataModel>(new LuaDataModel());
+ dm->_interpreter = interpreter;
+ dm->_luaState = luaL_newstate();
+ luaL_openlibs(dm->_luaState);
+
+ luabridge::getGlobalNamespace(dm->_luaState).beginClass<InterpreterImpl>("__interpreter").endClass();
+ luabridge::getGlobalNamespace(dm->_luaState).addCFunction("In", luaInFunction);
+
+ luabridge::setGlobal(dm->_luaState, dm->_interpreter, "__interpreter");
+
+ return dm;
+}
+
+LuaDataModel::~LuaDataModel() {
+ if (_luaState != NULL)
+ lua_close(_luaState);
+}
+
+void LuaDataModel::pushContext() {
+}
+
+void LuaDataModel::popContext() {
+}
+
+void LuaDataModel::initialize() {
+}
+
+void LuaDataModel::setEvent(const Event& event) {
+}
+
+Data LuaDataModel::getStringAsData(const std::string& content) {
+ Data data = Data::fromJSON(content);
+ if (data.empty()) {
+ data = Data(content, Data::VERBATIM);
+ }
+ return data;
+}
+
+bool LuaDataModel::validate(const std::string& location, const std::string& schema) {
+ return true;
+}
+
+bool LuaDataModel::isLocation(const std::string& expr) {
+ return true;
+}
+
+uint32_t LuaDataModel::getLength(const std::string& expr) {
+ return 0;
+}
+
+void LuaDataModel::setForeach(const std::string& item,
+ const std::string& array,
+ const std::string& index,
+ uint32_t iteration) {
+}
+
+void LuaDataModel::eval(const Arabica::DOM::Element<std::string>& scriptElem,
+ const std::string& expr) {
+
+}
+
+bool LuaDataModel::isDeclared(const std::string& expr) {
+ return true;
+}
+
+void LuaDataModel::assign(const Arabica::DOM::Element<std::string>& assignElem,
+ const Arabica::DOM::Node<std::string>& node,
+ const std::string& content) {
+
+}
+
+void LuaDataModel::assign(const std::string& location, const Data& data) {
+
+}
+
+void LuaDataModel::init(const Arabica::DOM::Element<std::string>& dataElem,
+ const Arabica::DOM::Node<std::string>& node,
+ const std::string& content) {
+
+}
+
+void LuaDataModel::init(const std::string& location, const Data& data) {
+
+}
+
+/**
+ * The boolean expression language consists of the In predicate only. It has the
+ * form 'In(id)', where id is the id of a state in the enclosing state machine.
+ * The predicate must return 'true' if and only if that state is in the current
+ * state configuration.
+ */
+bool LuaDataModel::evalAsBool(const Arabica::DOM::Node<std::string>& node, 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);
+ if (!boost::starts_with(trimmedExpr, "return")) {
+ 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 stackSize = lua_gettop(_luaState);
+ if (stackSize != 1)
+ return false;
+ if (lua_isboolean(_luaState, -1))
+ return lua_toboolean(_luaState, -1);
+ return false;
+}
+
+
+std::string LuaDataModel::evalAsString(const std::string& expr) {
+ return expr;
+}
+
+double LuaDataModel::evalAsNumber(const std::string& expr) {
+ return 0;
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/lua/LuaDataModel.h b/src/uscxml/plugins/datamodel/lua/LuaDataModel.h
new file mode 100644
index 0000000..9677307
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/lua/LuaDataModel.h
@@ -0,0 +1,111 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef LUADATAMODEL_H_113E014C
+#define LUADATAMODEL_H_113E014C
+
+#include "uscxml/Interpreter.h"
+#include <list>
+
+#ifdef BUILD_AS_PLUGINS
+#include "uscxml/plugins/Plugins.h"
+#endif
+
+extern "C" {
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+}
+
+namespace uscxml {
+class Event;
+class Data;
+}
+
+namespace uscxml {
+
+class LuaDataModel : public DataModelImpl {
+public:
+ LuaDataModel();
+ virtual ~LuaDataModel();
+ virtual boost::shared_ptr<DataModelImpl> create(InterpreterImpl* interpreter);
+
+ virtual std::list<std::string> getNames() {
+ std::list<std::string> names;
+ names.push_back("lua");
+ return names;
+ }
+
+ virtual void initialize();
+ virtual void setEvent(const Event& event);
+
+ virtual bool validate(const std::string& location, const std::string& schema);
+ virtual bool isLocation(const std::string& expr);
+
+ virtual uint32_t getLength(const std::string& expr);
+ virtual void setForeach(const std::string& item,
+ const std::string& array,
+ const std::string& index,
+ uint32_t iteration);
+
+ virtual void pushContext();
+ virtual void popContext();
+
+ virtual void assign(const Arabica::DOM::Element<std::string>& assignElem,
+ const Arabica::DOM::Node<std::string>& node,
+ const std::string& content);
+ virtual void assign(const std::string& location, const Data& data);
+
+ virtual void init(const Arabica::DOM::Element<std::string>& dataElem,
+ const Arabica::DOM::Node<std::string>& node,
+ const std::string& content);
+ virtual void init(const std::string& location, const Data& data);
+
+ virtual Data getStringAsData(const std::string& content);
+ virtual bool isDeclared(const std::string& expr);
+
+ virtual void eval(const Arabica::DOM::Element<std::string>& scriptElem,
+ 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:
+
+ 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);
+
+ lua_State* _luaState;
+};
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_INHERIT_PROVIDER(LuaDataModel, DataModelImpl);
+#endif
+
+}
+
+#endif /* end of include guard: LUADATAMODEL_H_113E014C */
diff --git a/test/uscxml/test-lua.scxml b/test/uscxml/test-lua.scxml
new file mode 100644
index 0000000..1168ca3
--- /dev/null
+++ b/test/uscxml/test-lua.scxml
@@ -0,0 +1,6 @@
+<scxml datamodel="lua" name="lua-test">
+ <state id="s1">
+ <transition cond="In('s1')" target="end" />
+ </state>
+ <state id="end" final="true" />
+</scxml>
diff --git a/test/w3c/lua/test144.scxml b/test/w3c/lua/test144.scxml
new file mode 100644
index 0000000..07d34b5
--- /dev/null
+++ b/test/w3c/lua/test144.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that events are inserted into the queue in the order in which they are raised. If
+foo occurs before bar, success, otherwise failure -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition event="foo" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition event="bar" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test147.scxml b/test/w3c/lua/test147.scxml
new file mode 100644
index 0000000..5e6d436
--- /dev/null
+++ b/test/w3c/lua/test147.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the first clause that evaluates to true - and only that clause - is executed.
+Only one event should be raised, and it should be bar -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <if cond="false">
+ <raise event="foo"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ <elseif cond="true"/>
+ <raise event="bar"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ <else/>
+ <raise event="baz"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </if>
+ <raise event="bat"/>
+ </onentry>
+ <transition event="bar" cond="testvar1 == 1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test148.scxml b/test/w3c/lua/test148.scxml
new file mode 100644
index 0000000..821fbf8
--- /dev/null
+++ b/test/w3c/lua/test148.scxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the else clause executes if <if> and <elseif> evaluate to false.
+Baz should be the only event generated by the <if>. bat is raised to catch the case where the <else> clause
+fails and baz is not generated, i.e. it makes sure that the test doesn't hang. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <if cond="false">
+ <raise event="foo"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ <elseif cond="false"/>
+ <raise event="bar"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ <else/>
+ <raise event="baz"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </if>
+ <raise event="bat"/>
+ </onentry>
+ <transition event="baz" cond="testvar1 == 1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test149.scxml b/test/w3c/lua/test149.scxml
new file mode 100644
index 0000000..a949d88
--- /dev/null
+++ b/test/w3c/lua/test149.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that neither if clause executes, so that bat is the only event raised. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <if cond="false">
+ <raise event="foo"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ <elseif cond="false"/>
+ <raise event="bar"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </if>
+ <raise event="bat"/>
+ </onentry>
+ <transition event="bat" cond="testvar1 == 0" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test150.scxml b/test/w3c/lua/test150.scxml
new file mode 100644
index 0000000..ea3ef06
--- /dev/null
+++ b/test/w3c/lua/test150.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that foreach causes a new variable to be declared if 'item' doesn't already exist. Also
+test that it will use an existing var if it does exist. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ <data id="testvar2"/>
+ <data id="testvar3">{1,2,3}</data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <!-- first use declared variables -->
+ <foreach array="testvar3" index="testvar2" item="testvar1"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error" target="fail"/>
+ <transition event="*" target="s1"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <!-- now use undeclared variables -->
+ <foreach array="testvar3" index="testvar5" item="testvar4"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition event="error" target="fail"/>
+ <transition event="*" target="s2"/>
+ </state>
+ <state id="s2">
+ <!-- check that var4 is bound -->
+ <transition cond="testvar4 ~= nil" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test151.scxml b/test/w3c/lua/test151.scxml
new file mode 100644
index 0000000..1950a2d
--- /dev/null
+++ b/test/w3c/lua/test151.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that foreach causes a new variable to be declared if 'item' doesn't already exist. Also
+test that it will use an existing var if it does exist. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ <data id="testvar2"/>
+ <data id="testvar3">{1,2,3}</data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <!-- first use declared variables -->
+ <foreach array="testvar3" index="testvar2" item="testvar1"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error" target="fail"/>
+ <transition event="*" target="s1"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <!-- now use undeclared variables -->
+ <foreach array="testvar3" index="testvar5" item="testvar4"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition event="error" target="fail"/>
+ <transition event="*" target="s2"/>
+ </state>
+ <state id="s2">
+ <!-- check that var5 is bound -->
+ <transition cond="testvar5 ~= nil" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test152.scxml b/test/w3c/lua/test152.scxml
new file mode 100644
index 0000000..1147c4b
--- /dev/null
+++ b/test/w3c/lua/test152.scxml
@@ -0,0 +1,41 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that an illegal array or item value causes error.execution and results in executable content
+not being executed. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <data id="testvar2"/>
+ <data id="testvar3"/>
+ <data expr="7" id="testvar4"/>
+ <data id="testvar5">{1,2,3}</data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <!-- invalid array, legal item -->
+ <foreach array="testvar4" index="testvar3" item="testvar2">
+ <assign location="testvar1" expr="testvar1+1"/>
+ </foreach>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <!-- illegal item, legal array -->
+ <foreach array="testvar5" index="testvar3" item="_no">
+ <assign location="testvar1" expr="testvar1+1"/>
+ </foreach>
+ <raise event="bar"/>
+ </onentry>
+ <transition event="error.execution" target="s2"/>
+ <transition event="bar" target="fail"/>
+ </state>
+ <state id="s2">
+ <!-- check that var1 has its original value (so executable content never got executed -->
+ <transition cond="testvar1 == 0" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test153.scxml b/test/w3c/lua/test153.scxml
new file mode 100644
index 0000000..5fd07d4
--- /dev/null
+++ b/test/w3c/lua/test153.scxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that foreach goes over the array in the right order. since the array contains 1 2 3, we compare the current
+value with the previous value, which is stored in var1. The current value should always be larger. If
+it ever isn't, set Var4 to 0, indicating failure -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <!-- contains the previous value -->
+ <data id="testvar2"/>
+ <!-- the item which will contain the current value -->
+ <data id="testvar3">{1,2,3}</data>
+ <data expr="1" id="testvar4"/>
+ <!-- 1 if success, 0 if failure -->
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <foreach array="testvar3" item="testvar2">
+ <if cond="testvar1 &lt; testvar2">
+ <assign expr="testvar2" location="testvar1"/>
+ <else/>
+ <!-- values are out of order, record failure -->
+ <assign expr="0" location="testvar4"/>
+ </if>
+ </foreach>
+ </onentry>
+ <!-- check that var1 has its original value -->
+ <transition cond="testvar4 == 0" target="fail"/>
+ <transition target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test155.scxml b/test/w3c/lua/test155.scxml
new file mode 100644
index 0000000..2064a37
--- /dev/null
+++ b/test/w3c/lua/test155.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that foreach executes the executable content once for each item in the list '(1,2,3)'. The executable
+content sums the items into var1 so it should be 6 at the end -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <data id="testvar2"/>
+ <data id="testvar3">{1,2,3}</data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <foreach array="testvar3" item="testvar2">
+ <assign location="testvar1" expr="testvar1+testvar2"/>
+ </foreach>
+ </onentry>
+ <transition cond="testvar1 == 6" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test156.scxml b/test/w3c/lua/test156.scxml
new file mode 100644
index 0000000..6eaff52
--- /dev/null
+++ b/test/w3c/lua/test156.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that an error causes the foreach to stop execution. The second piece of executable content
+should cause an error, so var1 should be incremented only once -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <data id="testvar2"/>
+ <data id="testvar3">{1,2,3}</data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <foreach array="testvar3" item="testvar2">
+ <assign location="testvar1" expr="testvar1+1"/>
+ <!-- assign an illegal value to a non-existent var -->
+ <assign expr="!" location="testvar5"/>
+ </foreach>
+ </onentry>
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test158.scxml b/test/w3c/lua/test158.scxml
new file mode 100644
index 0000000..8702557
--- /dev/null
+++ b/test/w3c/lua/test158.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that executable content executes in document order. if event1 occurs then event2, succeed, otherwise fail -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <raise event="event1"/>
+ <raise event="event2"/>
+ </onentry>
+ <transition event="event1" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test159.scxml b/test/w3c/lua/test159.scxml
new file mode 100644
index 0000000..5415b31
--- /dev/null
+++ b/test/w3c/lua/test159.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that any error raised by an element of executable content causes all subsequent elements to be skipped.
+The send tag will raise an error so var1 should not be incremented. If it is fail, otherwise succeed -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="thisWillFail" target="xxxxxxxxx"/>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onentry>
+ <transition cond="testvar1 == 1" target="fail"/>
+ <transition target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test172.scxml b/test/w3c/lua/test172.scxml
new file mode 100644
index 0000000..f8876e3
--- /dev/null
+++ b/test/w3c/lua/test172.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that eventexpr uses the current value of var1, not its initial value -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="'event1'" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="'event2'" location="testvar1"/>
+ <send eventexpr="testvar1"/>
+ </onentry>
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test173.scxml b/test/w3c/lua/test173.scxml
new file mode 100644
index 0000000..c904438
--- /dev/null
+++ b/test/w3c/lua/test173.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that targetexpr uses the current value of var1, not its initial value
+(If it uses the initial value, it will generate an error. If it uses the current value, event1 will be raised -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="-1" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="'#_internal'" location="testvar1"/>
+ <send event="event1" targetexpr="testvar1"/>
+ </onentry>
+ <transition event="event1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test174.scxml b/test/w3c/lua/test174.scxml
new file mode 100644
index 0000000..02d22b6
--- /dev/null
+++ b/test/w3c/lua/test174.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that typeexpr uses the current value of var1, not its initial value
+(If it uses the initial value, it will generate an error. If it uses the current value, event1 will be raised -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="27" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" location="testvar1"/>
+ <send event="event1" typeexpr="testvar1"/>
+ </onentry>
+ <transition event="event1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test175.scxml b/test/w3c/lua/test175.scxml
new file mode 100644
index 0000000..17da2c7
--- /dev/null
+++ b/test/w3c/lua/test175.scxml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that delayexpr uses the current value of var1, not its initial value
+(If it uses the initial value, event2 will be generated first, before event1. If it uses the current value,
+event1 will be raised first. Succeed if event1 occurs before event2, otherwise fail -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="'0s'" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="'1s'" location="testvar1"/>
+ <send event="event2" delayexpr="testvar1"/>
+ <send event="event1" delay="0ms"/>
+ </onentry>
+ <transition event="event1" target="s1"/>
+ <transition event="event2" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test176.scxml b/test/w3c/lua/test176.scxml
new file mode 100644
index 0000000..97f8f51
--- /dev/null
+++ b/test/w3c/lua/test176.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that <param> uses the current value of var1, not its initial value. If the value of
+aParam in event1 is 2 so that var2 gets set to 2, success, otherwise failure -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="2" location="testvar1"/>
+ <send event="event1">
+ <param name="aParam" expr="testvar1"/>
+ </send>
+ </onentry>
+ <transition event="event1" target="s1">
+ <assign expr="_event.data.aParam" location="testvar2"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar2 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test178.scxml b/test/w3c/lua/test178.scxml
new file mode 100644
index 0000000..11361e1
--- /dev/null
+++ b/test/w3c/lua/test178.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that multiple key/value pairs are included, even when the keys are the same.
+This is a manual test. The tester must look at the log output and verify that both
+keys are there. (This test uses the SCXML Event I/O processor, which is the only
+one that all platforms must support. It does not specify the message format, so
+we cannot test _event.raw directly. Therefore we print it out for visual
+inspection.) -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="event1">
+ <param expr="2" name="testvar1"/>
+ <param expr="3" name="testvar1"/>
+ </send>
+ </onentry>
+ <transition event="event1" target="final">
+ <log label="_event " expr="_event:inspect(true)"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="final"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test179.scxml b/test/w3c/lua/test179.scxml
new file mode 100644
index 0000000..c8647c7
--- /dev/null
+++ b/test/w3c/lua/test179.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that <content> can be used to populate body of a message -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="event1">
+ <content>123</content>
+ </send>
+ </onentry>
+ <transition event="event1" cond="_event.data == 123" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test183.scxml b/test/w3c/lua/test183.scxml
new file mode 100644
index 0000000..2b36df9
--- /dev/null
+++ b/test/w3c/lua/test183.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that <send> stores the value of the sendid in idlocation. If it does,
+var1 has a value and we pass. Otherwise we fail -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="event1" idlocation="'testvar1'"/>
+ </onentry>
+ <transition cond="testvar1 ~= nil" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test185.scxml b/test/w3c/lua/test185.scxml
new file mode 100644
index 0000000..bb1281e
--- /dev/null
+++ b/test/w3c/lua/test185.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that <send> respects the delay specification. If it does, event1 arrives before event2
+ and we pass. Otherwise we fail -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="event2" delay="100ms"/>
+ <send event="event1"/>
+ </onentry>
+ <transition event="event1" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test186.scxml b/test/w3c/lua/test186.scxml
new file mode 100644
index 0000000..f0a6fc4
--- /dev/null
+++ b/test/w3c/lua/test186.scxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that <send> evals its args when it is evaluated, not when the delay interval expires and the
+message is actually sent. If it does, aParam will have the value of 1 (even though var1 has been incremented
+in the interval.) If var2 ends up == 1, we pass. Otherwise we fail -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="event1" delay="100ms">
+ <param name="aParam" expr="testvar1"/>
+ </send>
+ <assign expr="2" location="testvar1"/>
+ </onentry>
+ <transition event="event1" target="s1">
+ <assign expr="_event.data.aParam" location="testvar2"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar2 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test187.scxml b/test/w3c/lua/test187.scxml
new file mode 100644
index 0000000..48aac56
--- /dev/null
+++ b/test/w3c/lua/test187.scxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that delayed <send> is not sent if the sending session terminates. In this case,
+a subscript is invoked which sends the event childToParent delayed by 1 second, and then terminates. The
+parent session, should not receive childToParent. If it does, we fail. Otherwise the
+10 sec timer expires and we pass -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="100ms"/>
+ </onentry>
+ <invoke type="scxml">
+ <content>
+ <!-- exit before the delayed send can execute -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send event="childToParent" target="#_parent" delay="0ms"/>
+ </onentry>
+ <transition target="subFinal"/>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="childToParent" target="fail"/>
+ <transition event="timeout" target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test189.scxml b/test/w3c/lua/test189.scxml
new file mode 100644
index 0000000..09abfc3
--- /dev/null
+++ b/test/w3c/lua/test189.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that #_internal as a target of <send> puts the event on the internal queue. If it does,
+event1 will be processed before event2, because event1 is added to the internal queue while event2 is
+added to the external queue (event though event2 is generated first) -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <!-- goes to the external queue -->
+ <send event="event2"/>
+ <!-- to the internal queue -->
+ <send event="event1" target="#_internal"/>
+ </onentry>
+ <!-- once we've entered the state, we should check for internal events first -->
+ <transition event="event1" target="pass"/>
+ <transition event="event2" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test190.scxml b/test/w3c/lua/test190.scxml
new file mode 100644
index 0000000..09ad268
--- /dev/null
+++ b/test/w3c/lua/test190.scxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that #_scxml_sessionid as a target of <send> puts the event on the external queue. If it does,
+event1 will be processed before event2, because event1 is added to the internal queue while event2 is
+added to the external queue (event though event2 is generated first). we have to make sure that event2
+is actually delivered. The delayed <send> makes sure another event is generated (so the test doesn't hang) -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="'#_scxml_'" id="testvar1"/>
+ <data expr="_sessionid" id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="testvar1" expr="testvar1..testvar2"/>
+ <!-- goes to the external queue -->
+ <send event="event2" targetexpr="testvar1"/>
+ <!-- to the internal queue -->
+ <raise event="event1"/>
+ <!-- this should get added to the external queue after event2 -->
+ <send event="timeout"/>
+ </onentry>
+ <!-- once we've entered the state, we should check for internal events first -->
+ <transition event="event1" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <!-- now check that we get event2 and not a timeout -->
+ <state id="s1">
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test191.scxml b/test/w3c/lua/test191.scxml
new file mode 100644
index 0000000..40b180a
--- /dev/null
+++ b/test/w3c/lua/test191.scxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that #_parent works as a target of <send> . a subscript is invoked and sends the event
+childToParent to its parent session (ths session) using #_parent as the target. If we get this event, we
+pass, otherwise we fail. The timer insures that some event is generated and that the test does not hang. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="5s"/>
+ </onentry>
+ <invoke type="scxml">
+ <content>
+ <!-- send an event to the parent session using #_parent as the target -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send event="childToParent" target="#_parent"/>
+ </onentry>
+ <transition target="subFinal"/>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="childToParent" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test192.scxml b/test/w3c/lua/test192.scxml
new file mode 100644
index 0000000..22be823
--- /dev/null
+++ b/test/w3c/lua/test192.scxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that #_invokeid works as a target of <send> . A child script is invoked and sends us
+childToParent once its running. Then we send it the event parentToChild using its invokeid as the target.
+If it receives this event, it sends sends the event eventReceived to its parent session (ths session).
+If we get this event, we pass, otherwise the child script eventually times out sends invoke.done and we fail.
+We also set a timeout in this process to make sure the test doesn't hang -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="5s"/>
+ </onentry>
+ <invoke type="scxml" id="invokedChild">
+ <content>
+ <!-- let the parent session know we're running by sending childToParent, then wait for parentToChild.
+ If we get it, send eventReceived. If we don't we eventually time out -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send event="childToParent" target="#_parent"/>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <transition event="parentToChild" target="subFinal">
+ <send target="#_parent" event="eventReceived"/>
+ </transition>
+ <transition event="timeout" target="subFinal"/>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="timeout" target="fail"/>
+ <transition event="done.invoke" target="fail"/>
+ <state id="s01">
+ <transition event="childToParent" target="s02">
+ <send target="#_invokedChild" event="parentToChild"/>
+ </transition>
+ </state>
+ <state id="s02">
+ <transition event="eventReceived" target="pass"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test193.scxml b/test/w3c/lua/test193.scxml
new file mode 100644
index 0000000..f533f5d
--- /dev/null
+++ b/test/w3c/lua/test193.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that omitting target and targetexpr of <send> when using the
+SCXML event i/o processor puts the event on the external queue. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="internal"/>
+ <!-- this should put event1 in the external queue -->
+ <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="event1" target="fail"/>
+ <transition event="internal" target="s1"/>
+ </state>
+ <state id="s1">
+ <transition event="event1" target="pass"/>
+ <transition event="timeout" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test194.scxml b/test/w3c/lua/test194.scxml
new file mode 100644
index 0000000..989e447
--- /dev/null
+++ b/test/w3c/lua/test194.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that specifying an illegal target for <send> causes the event error.execution to be raised. If it does,
+we succeed. Otherwise we eventually timeout and fail. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <!-- should cause an error -->
+ <send event="event2" target="xxxxxxxxx"/>
+ <!-- this will get added to the external event queue after the error has been raised -->
+ <send event="timeout"/>
+ </onentry>
+ <!-- once we've entered the state, we should check for internal events first -->
+ <transition event="error.execution" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test198.scxml b/test/w3c/lua/test198.scxml
new file mode 100644
index 0000000..e4a5be0
--- /dev/null
+++ b/test/w3c/lua/test198.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that if type is not provided <send> uses the scxml event i/o processor. The only way to tell
+what processor was used is to look at the origintype of the resulting event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="event1"/>
+ <send event="timeout"/>
+ </onentry>
+ <transition event="event1" cond="_event.origintype == 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test199.scxml b/test/w3c/lua/test199.scxml
new file mode 100644
index 0000000..9d152ff
--- /dev/null
+++ b/test/w3c/lua/test199.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that using an invalid send type results in error.execution -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="event1" type="27"/>
+ <send event="timeout"/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test200.scxml b/test/w3c/lua/test200.scxml
new file mode 100644
index 0000000..cfb3837
--- /dev/null
+++ b/test/w3c/lua/test200.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that the processor supports the scxml event i/o processor -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event1"/>
+ <send event="timeout"/>
+ </onentry>
+ <transition event="event1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test201.scxml b/test/w3c/lua/test201.scxml
new file mode 100644
index 0000000..f5f30f6
--- /dev/null
+++ b/test/w3c/lua/test201.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that the processor supports the basic http event i/o processor. This is an optional
+test since platforms are not required to support basic http event i/o -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" event="event1" targetexpr="FIXME"/>
+ <send event="timeout"/>
+ </onentry>
+ <transition event="event1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test205.scxml b/test/w3c/lua/test205.scxml
new file mode 100644
index 0000000..3f09cb5
--- /dev/null
+++ b/test/w3c/lua/test205.scxml
@@ -0,0 +1,26 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that the processor doesn't change the message. We can't test that it never does this, but
+at least we can check that the event name and included data are the same as we sent. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="event1">
+ <param name="aParam" expr="1"/>
+ </send>
+ <send event="timeout"/>
+ </onentry>
+ <transition event="event1" target="s1">
+ <assign expr="_event.data.aParam" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test207.scxml b/test/w3c/lua/test207.scxml
new file mode 100644
index 0000000..0672356
--- /dev/null
+++ b/test/w3c/lua/test207.scxml
@@ -0,0 +1,47 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that that we can't cancel an event in another session. We invoke a child process. It notifies
+us when it has generated a delayed event with sendid foo. We try to cancel foo. The child process sends us event
+ event success if the event is not cancelled, event fail otherwise. This doesn't test that there is absolutely no way to cancel an event
+raised in another session, but the spec doesn't define any way to refer to an event in another process -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="200ms"/>
+ </onentry>
+ <invoke type="scxml">
+ <content>
+ <!-- when invoked, we raise a delayed event1 with sendid 'foo' and notify our parent. Then we wait.
+ If event1 occurs, the parent hasn't succeeded in canceling it and we return pass. If event2 occurs
+ it means event1 was canceled (because event2 is delayed longer than event1) and we return 'fail'. -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send event="event1" id="foo" delay="100ms"/>
+ <send event="event2" delay="100ms"/>
+ <send target="#_parent" event="childToParent"/>
+ </onentry>
+ <transition event="event1" target="subFinal">
+ <send target="#_parent" event="pass"/>
+ </transition>
+ <transition event="*" target="subFinal">
+ <send target="#_parent" event="fail"/>
+ </transition>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <state id="s01">
+ <transition event="childToParent" target="s02">
+ <cancel sendid="foo"/>
+ </transition>
+ </state>
+ <state id="s02">
+ <transition event="pass" target="pass"/>
+ <transition event="fail" target="fail"/>
+ <transition event="timeout" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test208.scxml b/test/w3c/lua/test208.scxml
new file mode 100644
index 0000000..3217f31
--- /dev/null
+++ b/test/w3c/lua/test208.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that cancel works. We cancel delayed event1. If cancel works, we get event2 first and pass. If
+we get event1 or an error first, cancel didn't work and we fail. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send id="foo" event="event1" delay="100ms"/>
+ <send event="event2" delay="100ms"/>
+ <cancel sendid="foo"/>
+ </onentry>
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test210.scxml b/test/w3c/lua/test210.scxml
new file mode 100644
index 0000000..2de3e1d
--- /dev/null
+++ b/test/w3c/lua/test210.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that sendidexpr works with cancel. If it takes the most recent value of var1, it should cancel
+delayed event1. Thus we get event2 first and pass. If we get event1 or an error first, cancel didn't work and we fail. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="'bar'" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send id="foo" event="event1" delay="100ms"/>
+ <send event="event2" delay="100ms"/>
+ <assign expr="'foo'" location="testvar1"/>
+ <cancel sendidexpr="testvar1"/>
+ </onentry>
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test215.scxml b/test/w3c/lua/test215.scxml
new file mode 100644
index 0000000..26d4819
--- /dev/null
+++ b/test/w3c/lua/test215.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that typexpr is evaluated at runtime. If the original value of var1 is used, the invocation
+will fail (test215sub1.scxml is not of type 'foo', even if the platform supports foo as a type). If
+the runtime value is used, the invocation will succeed -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="'foo'" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="5s"/>
+ <assign expr="'http://www.w3.org/TR/scxml/'" location="testvar1"/>
+ </onentry>
+ <invoke typeexpr="testvar1">
+ <content>
+ <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. -->
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="done.invoke" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test216.scxml b/test/w3c/lua/test216.scxml
new file mode 100644
index 0000000..5a09fc7
--- /dev/null
+++ b/test/w3c/lua/test216.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that srcexpr is evaluated at runtime. If the original value of var1 is used, the invocation
+will fail (assuming that there is no script named 'foo'). If
+the runtime value is used, the invocation will succeed -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="'foo'" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="5s"/>
+ <assign expr="'file:test216sub1.scxml'" location="testvar1"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml" srcexpr="testvar1"/>
+ <transition event="done.invoke" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test216sub1.scxml b/test/w3c/lua/test216sub1.scxml
new file mode 100644
index 0000000..e1d9195
--- /dev/null
+++ b/test/w3c/lua/test216sub1.scxml
@@ -0,0 +1,5 @@
+<?xml version="1.0" standalone="no"?>
+<!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="final" version="1.0" datamodel="lua">
+ <final id="final"/>
+</scxml>
diff --git a/test/w3c/lua/test220.scxml b/test/w3c/lua/test220.scxml
new file mode 100644
index 0000000..bf1ef9d
--- /dev/null
+++ b/test/w3c/lua/test220.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that the scxml type is supported. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="5s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. -->
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="done.invoke" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test223.scxml b/test/w3c/lua/test223.scxml
new file mode 100644
index 0000000..92cf1a9
--- /dev/null
+++ b/test/w3c/lua/test223.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that idlocation is supported. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" idlocation="'testvar1'">
+ <content>
+ <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. -->
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="*" target="s1"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1 ~= nil" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test224.scxml b/test/w3c/lua/test224.scxml
new file mode 100644
index 0000000..7a095e0
--- /dev/null
+++ b/test/w3c/lua/test224.scxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that the automatically generated id has the form stateid.platformid. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ <data expr="'s0.'" id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" idlocation="'testvar1'">
+ <content>
+ <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. -->
+ <scxml version="1.0" initial="subFinal" datamodel="lua">
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="*" target="s1"/>
+ </state>
+ <state id="s1">
+ <transition cond="string.sub(testvar1,1,string.len(testvar2))==testvar2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test225.scxml b/test/w3c/lua/test225.scxml
new file mode 100644
index 0000000..d370f9b
--- /dev/null
+++ b/test/w3c/lua/test225.scxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that the automatically generated id is unique, we call invoke twice and compare the ids. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" idlocation="'testvar1'">
+ <content>
+ <scxml initial="subFinal1" version="1.0" datamodel="lua">
+ <final id="subFinal1"/>
+ </scxml>
+ </content>
+ </invoke>
+ <invoke type="http://www.w3.org/TR/scxml/" idlocation="'testvar2'">
+ <content>
+ <scxml initial="subFinal2" version="1.0" datamodel="lua">
+ <final id="subFinal2"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="*" target="s1"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1==testvar2" target="fail"/>
+ <transition target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test226.scxml b/test/w3c/lua/test226.scxml
new file mode 100644
index 0000000..35351d3
--- /dev/null
+++ b/test/w3c/lua/test226.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!-- this is basically just a test that invoke works correctly and that you can pass data
+to the invoked process. If the invoked session finds aParam==1, it exits, signalling
+success. otherwise it will hang and the timeout in this doc signifies failure. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" src="file:test226sub1.scxml">
+ <param expr="1" name="testvar1"/>
+ </invoke>
+ <transition event="varBound" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test226sub1.scxml b/test/w3c/lua/test226sub1.scxml
new file mode 100644
index 0000000..75dde69
--- /dev/null
+++ b/test/w3c/lua/test226sub1.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- when invoked, if var1 has a value notify parent. Then terminate. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <transition target="final" cond="testvar1 ~= nil">
+ <send target="#_parent" event="varBound"/>
+ </transition>
+ <transition target="final"/>
+ </state>
+ <final id="final"/>
+</scxml>
diff --git a/test/w3c/lua/test228.scxml b/test/w3c/lua/test228.scxml
new file mode 100644
index 0000000..b81675f
--- /dev/null
+++ b/test/w3c/lua/test228.scxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the invokeid is included in events returned from the invoked process. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" id="foo">
+ <content>
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="done.invoke" target="s1">
+ <assign expr="_event.invokeid" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1 == 'foo'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test229.scxml b/test/w3c/lua/test229.scxml
new file mode 100644
index 0000000..b11bd8c
--- /dev/null
+++ b/test/w3c/lua/test229.scxml
@@ -0,0 +1,38 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that autofoward works. If the child process receives back a copy of the
+childToParent event that it sends to this doc, it sends eventReceived, signalling success. (Note
+that this doc is not required to process that event explicitly. It should be forwarded in any case.) Otherwise
+it eventually times out and the done.invoke signals failure -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" autoforward="true">
+ <content>
+ <!-- when invoked, send childToParent to parent.
+ If it is forwarded back to us, send
+ eventReceived to signal success and terminate.
+ Otherwise wait for timer to expire and terminate. -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send target="#_parent" event="childToParent"/>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <transition event="childToParent" target="subFinal">
+ <send target="#_parent" event="eventReceived"/>
+ </transition>
+ <transition event="*" target="subFinal"/>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="childToParent"/>
+ <transition event="eventReceived" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test230.scxml b/test/w3c/lua/test230.scxml
new file mode 100644
index 0000000..33b1239
--- /dev/null
+++ b/test/w3c/lua/test230.scxml
@@ -0,0 +1,56 @@
+<?xml version="1.0" standalone="no"?>
+<!-- a manual test that an autofowarded event has the same fields and values as the original event.
+the child process sends the parent process an event which is forwarded back to it.
+Both the parent and child process print out the contents of the event. The tester
+must check if they are the same and report his result. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" autoforward="true">
+ <content>
+ <!-- when invoked, send childToParent to parent. If it is forwarded back to us, print out its
+ fields and terminate. -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send target="#_parent" event="childToParent"/>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <transition event="childToParent" target="subFinal">
+ <log label="name is " expr="_event.name"/>
+ <log label="type is " expr="_event.type"/>
+ <log label="sendid is " expr="_event.sendid"/>
+ <log label="origin is " expr="_event.origin"/>
+ <log label="origintype is " expr="_event.origintype"/>
+ <log label="invokeid is " expr="_event.invokeid"/>
+ <log label="data is " expr="_event.data"/>
+ </transition>
+ <transition event="*" target="subFinal"/>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="timeout" target="final"/>
+ <state id="s01">
+ <transition event="childToParent" target="s02">
+ <log label="name is " expr="_event.name"/>
+ <log label="type is " expr="_event.type"/>
+ <log label="sendid is " expr="_event.sendid"/>
+ <log label="origin is " expr="_event.origin"/>
+ <log label="origintype is " expr="_event.origintype"/>
+ <log label="invokeid is " expr="_event.invokeid"/>
+ <log label="data is " expr="_event.data"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s02">
+ <!-- wait till we get the done event to ensure that the child process has time to print out its results -->
+ <transition event="done.invoke" target="final"/>
+ </state>
+ </state>
+ <final id="final"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test232.scxml b/test/w3c/lua/test232.scxml
new file mode 100644
index 0000000..8e7503e
--- /dev/null
+++ b/test/w3c/lua/test232.scxml
@@ -0,0 +1,33 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that a parent process can receive multiple events from a child process -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal">
+ <onentry>
+ <send target="#_parent" event="childToParent1"/>
+ <send target="#_parent" event="childToParent2"/>
+ </onentry>
+ </final>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="timeout" target="fail"/>
+ <state id="s01">
+ <transition event="childToParent1" target="s02"/>
+ </state>
+ <state id="s02">
+ <transition event="childToParent2" target="s03"/>
+ </state>
+ <state id="s03">
+ <transition event="done.invoke" target="pass"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test233.scxml b/test/w3c/lua/test233.scxml
new file mode 100644
index 0000000..ea6975b
--- /dev/null
+++ b/test/w3c/lua/test233.scxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that finalize markup runs before the event is processed. The invoked process will
+return 2 in _event.data.aParam, so that new value should be in force when we select
+the transtitions. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal">
+ <onentry>
+ <send target="#_parent" event="childToParent">
+ <param name="aParam" expr="2"/>
+ </send>
+ </onentry>
+ </final>
+ </scxml>
+ </content>
+ <finalize>
+ <assign expr="_event.data.aParam" location="testvar1"/>
+ </finalize>
+ </invoke>
+ <transition event="childToParent" cond="testvar1 == 2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test234.scxml b/test/w3c/lua/test234.scxml
new file mode 100644
index 0000000..a99b053
--- /dev/null
+++ b/test/w3c/lua/test234.scxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that only finalize markup in the invoking state runs. the first invoked process will
+return 2 in _event.data.aParam, while second invoked process sleeps without returning any events.
+Only the first finalize should execute. So when we get to s1 var1 should have value 2 but
+var2 should still be set to 1 -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="p0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ <data expr="1" id="testvar2"/>
+ </datamodel>
+ <parallel id="p0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="p01">
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml version="1.0" initial="subFinal1" datamodel="lua">
+ <final id="subFinal1">
+ <onentry>
+ <send target="#_parent" event="childToParent">
+ <param name="aParam" expr="2"/>
+ </send>
+ </onentry>
+ </final>
+ </scxml>
+ </content>
+ <finalize>
+ <assign expr="_event.data.aParam" location="testvar1"/>
+ </finalize>
+ </invoke>
+ <transition event="childToParent" target="s1" cond="testvar1 == 2"/>
+ <transition event="childToParent" target="fail"/>
+ </state>
+ <state id="p02">
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml version="1.0" initial="sub0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <transition event="timeout" target="subFinal2"/>
+ </state>
+ <final id="subFinal2"/>
+ </scxml>
+ </content>
+ <finalize>
+ <assign expr="_event.data.aParam" location="testvar2"/>
+ </finalize>
+ </invoke>
+ </state>
+ </parallel>
+ <state id="s1">
+ <transition cond="testvar2 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test235.scxml b/test/w3c/lua/test235.scxml
new file mode 100644
index 0000000..4575cc5
--- /dev/null
+++ b/test/w3c/lua/test235.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that done.invoke.id event has the right id. the invoked child terminates immediately
+and should generate done.invoke.foo -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" id="foo">
+ <content>
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="done.invoke.foo" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test236.scxml b/test/w3c/lua/test236.scxml
new file mode 100644
index 0000000..333c68b
--- /dev/null
+++ b/test/w3c/lua/test236.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that done.invoke.id event is the last event we receive. the invoked process sends childToParent
+in the exit handler of its final state. We should get it before the done.invoke, and we should get no
+events after the done.invoke. Hence timeout indicates success -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="200ms"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal">
+ <onexit>
+ <send target="#_parent" event="childToParent"/>
+ </onexit>
+ </final>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="childToParent" target="s1"/>
+ <transition event="done.invoke" target="fail"/>
+ </state>
+ <state id="s1">
+ <!-- here we should get done.invoke -->
+ <transition event="done.invoke" target="s2"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s2">
+ <transition event="timeout" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test237.scxml b/test/w3c/lua/test237.scxml
new file mode 100644
index 0000000..b64f87f
--- /dev/null
+++ b/test/w3c/lua/test237.scxml
@@ -0,0 +1,37 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that cancelling works. invoked child sleeps for two seconds, then terminates. We
+sleep for 1 sec in s0, then move to s1. This should cause the invocation to get cancelled.
+If we receive done.invoke, the invocation wasn't cancelled, and we fail. If we receive no events by
+the time timeout2 fires, success -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout1" delay="100ms"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <!-- when invoked, sleep for 2 secs then terminate. Parent will try to cancel this session -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send event="timeout" delay="200ms"/>
+ </onentry>
+ <transition event="timeout" target="subFinal"/>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="timeout1" target="s1"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <send event="timeout2" delay="100ms"/>
+ </onentry>
+ <!-- here we should NOT get done.invoke -->
+ <transition event="done.invoke" target="fail"/>
+ <transition event="*" target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test239.scxml b/test/w3c/lua/test239.scxml
new file mode 100644
index 0000000..dc3fff9
--- /dev/null
+++ b/test/w3c/lua/test239.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that markup can be specified both by 'src' and by <content> -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s01">
+ <invoke type="http://www.w3.org/TR/scxml/" src="file:test239sub1.scxml"/>
+ <transition event="done.invoke" target="s02"/>
+ </state>
+ <state id="s02">
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <!-- identical to test239sub1.scxml. -->
+ <content>
+ <scxml version="1.0" initial="final" datamodel="lua">
+ <final id="final"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="done.invoke" target="pass"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test239sub1.scxml b/test/w3c/lua/test239sub1.scxml
new file mode 100644
index 0000000..4720f59
--- /dev/null
+++ b/test/w3c/lua/test239sub1.scxml
@@ -0,0 +1,5 @@
+<?xml version="1.0" standalone="no"?>
+<!-- when invoked, just terminate. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="final" version="1.0" datamodel="lua">
+ <final id="final"/>
+</scxml>
diff --git a/test/w3c/lua/test240.scxml b/test/w3c/lua/test240.scxml
new file mode 100644
index 0000000..bd79eb6
--- /dev/null
+++ b/test/w3c/lua/test240.scxml
@@ -0,0 +1,63 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that datamodel values can be specified both by 'namelist' and by <param>.
+invoked child will return success if its Var1 is set to 1, failure otherwise. This
+test will fail schema validation because of the multiple occurences of Var1, but
+should run correctly. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s01">
+ <invoke type="http://www.w3.org/TR/scxml/" namelist="testvar1">
+ <content>
+ <scxml initial="sub01" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="sub01">
+ <transition target="subFinal1" cond="testvar1 == 1">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal1">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ </state>
+ <final id="subFinal1"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="success" target="s02"/>
+ <transition event="failure" target="fail"/>
+ </state>
+ <state id="s02">
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <param expr="1" name="testvar1"/>
+ <content>
+ <scxml initial="sub02" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="sub02">
+ <transition target="subFinal2" cond="testvar1 == 1">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal1">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ </state>
+ <final id="subFinal2"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="success" target="pass"/>
+ <transition event="failure" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test241.scxml b/test/w3c/lua/test241.scxml
new file mode 100644
index 0000000..e476227
--- /dev/null
+++ b/test/w3c/lua/test241.scxml
@@ -0,0 +1,88 @@
+<?xml version="1.0" standalone="no"?>
+<!-- The child process will return success ifits Var1 is set to 1, failure otherwise. For this test
+we try passing in Var1 by param and by namelist and check that we either get two successes
+or two failures. This test will fail schema validation due to multiple declarations of
+Var1, but should run correctly. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s01">
+ <invoke type="http://www.w3.org/TR/scxml/" namelist="testvar1">
+ <content>
+ <scxml initial="sub01" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="sub01">
+ <transition target="subFinal1" cond="testvar1 == 1">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal1">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ </state>
+ <final id="subFinal1"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="success" target="s02"/>
+ <transition event="failure" target="s03"/>
+ </state>
+ <state id="s02">
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <param expr="1" name="testvar1"/>
+ <content>
+ <scxml initial="sub02" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="sub02">
+ <transition target="subFinal2" cond="testvar1 == 1">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal2">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ </state>
+ <final id="subFinal2"/>
+ </scxml>
+ </content>
+ </invoke>
+ <!-- we got success in s01, so we need to do so here -->
+ <transition event="success" target="pass"/>
+ <transition event="failure" target="fail"/>
+ </state>
+ <state id="s03">
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <param expr="1" name="testvar1"/>
+ <content>
+ <scxml initial="sub03" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="sub03">
+ <transition target="subFinal3" cond="testvar1 == 1">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal3">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ </state>
+ <final id="subFinal3"/>
+ </scxml>
+ </content>
+ </invoke>
+ <!-- we got failure in s01, so we need to do so here -->
+ <transition event="failure" target="pass"/>
+ <transition event="success" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test242.scxml b/test/w3c/lua/test242.scxml
new file mode 100644
index 0000000..36e8034
--- /dev/null
+++ b/test/w3c/lua/test242.scxml
@@ -0,0 +1,48 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that markup specified by 'src' and by <content> is treated the same way. That means that
+either we get done.invoke in both cases or in neither case (in which case we timeout) -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout1" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <invoke type="http://www.w3.org/TR/scxml/" src="file:test242sub1.scxml"/>
+ <transition event="done.invoke" target="s02"/>
+ <transition event="timeout1" target="s03"/>
+ </state>
+ <state id="s02">
+ <onentry>
+ <send event="timeout2" delay="1s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <!-- identical to test242sub1.scxml. -->
+ <content>
+ <scxml version="1.0" initial="subFinal1" datamodel="lua">
+ <final id="subFinal1"/>
+ </scxml>
+ </content>
+ </invoke>
+ <!-- we got done.invoke last time, so we need it this time too -->
+ <transition event="done.invoke" target="pass"/>
+ <transition event="timeout2" target="fail"/>
+ </state>
+ <state id="s03">
+ <onentry>
+ <send event="timeout3" delay="1s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <!-- identical to test242sub1.scxml. -->
+ <content>
+ <scxml version="1.0" initial="subFinal2" datamodel="lua">
+ <final id="subFinal2"/>
+ </scxml>
+ </content>
+ </invoke>
+ <!-- we got timeout last time, so we need it this time too -->
+ <transition event="timeout3" target="pass"/>
+ <transition event="done.invoke" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test242sub1.scxml b/test/w3c/lua/test242sub1.scxml
new file mode 100644
index 0000000..4720f59
--- /dev/null
+++ b/test/w3c/lua/test242sub1.scxml
@@ -0,0 +1,5 @@
+<?xml version="1.0" standalone="no"?>
+<!-- when invoked, just terminate. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="final" version="1.0" datamodel="lua">
+ <final id="final"/>
+</scxml>
diff --git a/test/w3c/lua/test243.scxml b/test/w3c/lua/test243.scxml
new file mode 100644
index 0000000..7e1f854
--- /dev/null
+++ b/test/w3c/lua/test243.scxml
@@ -0,0 +1,33 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that datamodel values can be specified by param.
+test240sub1 will return success ifits Var1 is set to 1, failure otherwise. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <param expr="1" name="testvar1"/>
+ <content>
+ <scxml version="1.0" initial="sub0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="sub0">
+ <transition target="subFinal" cond="testvar1 == 1">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="success" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test244.scxml b/test/w3c/lua/test244.scxml
new file mode 100644
index 0000000..a6e6c95
--- /dev/null
+++ b/test/w3c/lua/test244.scxml
@@ -0,0 +1,37 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that datamodel values can be specified by namelist.
+invoked child will return success ifits Var1 is set to 1, failure otherwise.
+This test will fail schema validation due to multiple occurrences of Var1,
+but should run correctly. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" namelist="testvar1">
+ <content>
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="sub0">
+ <transition target="subFinal" cond="testvar1 == 1">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="success" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test245.scxml b/test/w3c/lua/test245.scxml
new file mode 100644
index 0000000..cb32e22
--- /dev/null
+++ b/test/w3c/lua/test245.scxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that non-existent datamodel values are not set. Var2 is not defined in
+invoked child's datamodel. It will will return success if its Var2 remains unbound, failure otherwise. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="3" id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" namelist="testvar2">
+ <content>
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <transition target="subFinal" cond="testvar2 ~= nil">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ <transition target="subFinal">
+ <send target="#_parent" event="success"/>
+ </transition>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="success" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test247.scxml b/test/w3c/lua/test247.scxml
new file mode 100644
index 0000000..cc7e910
--- /dev/null
+++ b/test/w3c/lua/test247.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that we get done.invoke. timeout indicates failure -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml version="1.0" initial="subFinal" datamodel="lua">
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="done.invoke" target="pass"/>
+ <transition event="timeout" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test250.scxml b/test/w3c/lua/test250.scxml
new file mode 100644
index 0000000..d522ad9
--- /dev/null
+++ b/test/w3c/lua/test250.scxml
@@ -0,0 +1,39 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the onexit handlers run in the invoked process if it is cancelled. This has to be a
+manual test, since this process won't accept any events from the child process once it has been cancelled.
+Tester must examine log output from child process to determine success -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="foo"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0" initial="sub01">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <transition event="timeout" target="subFinal"/>
+ <onexit>
+ <log expr="'Exiting sub0'"/>
+ </onexit>
+ <state id="sub01">
+ <onexit>
+ <log expr="'Exiting sub01'"/>
+ </onexit>
+ </state>
+ </state>
+ <final id="subFinal">
+ <onentry>
+ <log expr="'entering final state, invocation was not cancelled'"/>
+ </onentry>
+ </final>
+ </scxml>
+ </content>
+ </invoke>
+ <!-- this transition will cause the invocation to be cancelled -->
+ <transition event="foo" target="final"/>
+ </state>
+ <final id="final"/>
+</scxml>
diff --git a/test/w3c/lua/test252.scxml b/test/w3c/lua/test252.scxml
new file mode 100644
index 0000000..29ae000
--- /dev/null
+++ b/test/w3c/lua/test252.scxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that we don't process any events received from the invoked process once it is cancelled. child
+process tries to send us childToParent in an onexit handler. If we get it, we fail.
+timeout indicates success. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="100ms"/>
+ </onentry>
+ <transition event="timeout" target="pass"/>
+ <transition event="childToParent" target="fail"/>
+ <transition event="done.invoke" target="fail"/>
+ <state id="s01">
+ <onentry>
+ <send event="foo"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send event="timeout" delay="0ms"/>
+ </onentry>
+ <transition event="timeout" target="subFinal"/>
+ <onexit>
+ <send target="#_parent" event="childToParent"/>
+ </onexit>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <!-- this transition will cause the invocation to be cancelled -->
+ <transition event="foo" target="s02"/>
+ </state>
+ <state id="s02"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test253.scxml b/test/w3c/lua/test253.scxml
new file mode 100644
index 0000000..1e9b626
--- /dev/null
+++ b/test/w3c/lua/test253.scxml
@@ -0,0 +1,67 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the scxml event processor is used in both directions. If child process uses the
+scxml event i/o processor to communicate with us, send it an event. It will send back success if
+this process uses the scxml processor to send the message to it, otherwise failure. For this test we allow
+'scxml' as an alternative to the full url. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <invoke type="scxml" id="foo">
+ <content>
+ <!-- inform parent we're running then wait for it to send us an event. If it uses the scxml event i/o
+ processor to do so, return success, otherwise return failure. -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="sub0">
+ <onentry>
+ <send target="#_parent" event="childRunning"/>
+ </onentry>
+ <transition event="parentToChild" target="sub1">
+ <assign expr="_event.origintype" location="testvar2"/>
+ </transition>
+ </state>
+ <state id="sub1">
+ <transition target="subFinal" cond="testvar2 == 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal" cond="testvar2 == 'scxml'">
+ <send target="#_parent" event="success"/>
+ </transition>
+ <transition target="subFinal">
+ <send target="#_parent" event="failure"/>
+ </transition>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <state id="s01">
+ <transition event="childRunning" target="s02">
+ <assign expr="_event.origintype" location="testvar1"/>
+ </transition>
+ </state>
+ <state id="s02">
+ <transition target="s03" cond="testvar1 == 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'">
+ <send target="#_foo" event="parentToChild"/>
+ </transition>
+ <transition target="s03" cond="testvar1 == 'scxml'">
+ <send target="#_foo" event="parentToChild"/>
+ </transition>
+ <transition target="fail"/>
+ </state>
+ <state id="s03">
+ <transition event="success" target="pass"/>
+ <transition event="fail" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test276.scxml b/test/w3c/lua/test276.scxml
new file mode 100644
index 0000000..6af188d
--- /dev/null
+++ b/test/w3c/lua/test276.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that values passed in from parent process override default values specified in the child, test276sub1.scxml.
+The child returns event1 if var1 has value 1, event0 if it has default value 0. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <invoke type="scxml" src="file:test276sub1.scxml">
+ <param expr="1" name="testvar1"/>
+ </invoke>
+ <transition event="event1" target="pass"/>
+ <transition event="event0" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test276sub1.scxml b/test/w3c/lua/test276sub1.scxml
new file mode 100644
index 0000000..7db93cd
--- /dev/null
+++ b/test/w3c/lua/test276sub1.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- define var1 with default value 0. Parent will invoke this process setting var1 = 1. Return event1 if var1 == 1, event0 otherwise -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <transition target="final" cond="testvar1 == 1">
+ <send target="#_parent" event="event1"/>
+ </transition>
+ <transition target="final">
+ <send target="#_parent" event="event0"/>
+ </transition>
+ </state>
+ <final id="final"/>
+</scxml>
diff --git a/test/w3c/lua/test277.scxml b/test/w3c/lua/test277.scxml
new file mode 100644
index 0000000..7c0301c
--- /dev/null
+++ b/test/w3c/lua/test277.scxml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that platform creates undound variable if we assign an illegal value to it. Thus
+ we can assign to it later in state s1. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="!" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="s1" cond="testvar1==nil"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <assign expr="1" location="testvar1"/>
+ </onentry>
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test278.scxml b/test/w3c/lua/test278.scxml
new file mode 100644
index 0000000..fdd9063
--- /dev/null
+++ b/test/w3c/lua/test278.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <!-- test that a variable can be accessed from a state that is outside its lexical scope -->
+ <state id="s0">
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test279.scxml b/test/w3c/lua/test279.scxml
new file mode 100644
index 0000000..1eaac16
--- /dev/null
+++ b/test/w3c/lua/test279.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- testing that in case of early binding variables are assigned values at init time, before
+ the state containing them is visited -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test280.scxml b/test/w3c/lua/test280.scxml
new file mode 100644
index 0000000..e7cd5b1
--- /dev/null
+++ b/test/w3c/lua/test280.scxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test late binding. var2 won't get bound until s1 is entered, so it shouldn't have a value in s0 and
+accessing it should cause an error. It should get bound before the onentry code in s1 so it should be
+possible access it there and assign its value to var1 -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" binding="late" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <transition target="s1" cond="testvar2==nil"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <datamodel>
+ <data expr="1" id="testvar2"/>
+ </datamodel>
+ <onentry>
+ <assign expr="testvar2" location="testvar1"/>
+ </onentry>
+ <transition cond="testvar1==testvar2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test286.scxml b/test/w3c/lua/test286.scxml
new file mode 100644
index 0000000..7c47d91
--- /dev/null
+++ b/test/w3c/lua/test286.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that assigment to a non-declared var causes an error. the transition on foo catches the case
+where no error is raised -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <assign expr="1" location=""/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test287.scxml b/test/w3c/lua/test287.scxml
new file mode 100644
index 0000000..68ad7a6
--- /dev/null
+++ b/test/w3c/lua/test287.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- a simple test that a legal value may be assigned to a valid data model location -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="1" location="testvar1"/>
+ </onentry>
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test294.scxml b/test/w3c/lua/test294.scxml
new file mode 100644
index 0000000..90c000e
--- /dev/null
+++ b/test/w3c/lua/test294.scxml
@@ -0,0 +1,38 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that a param inside donedata ends up in the data field of the done event and
+that content inside donedata sets the full value of the event.data field -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="s01">
+ <transition event="done.state.s0" target="s1" cond="_event.data['testvar1'] == 1">
+ </transition>
+ <transition event="done.state.s0" target="fail">
+ </transition>
+ <state id="s01">
+ <transition target="s02"/>
+ </state>
+ <final id="s02">
+ <donedata>
+ <param expr="1" name="testvar1"/>
+ </donedata>
+ </final>
+ </state>
+ <state id="s1" initial="s11">
+ <transition event="done.state.s1" cond="_event.data == 'foo'" target="pass">
+ </transition>
+ <transition event="done.state.s1" target="fail">
+ </transition>
+ <state id="s11">
+ <transition target="s12"/>
+ </state>
+ <final id="s12">
+ <donedata>
+ <content expr="'foo'"/>
+ </donedata>
+ </final>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test298.scxml b/test/w3c/lua/test298.scxml
new file mode 100644
index 0000000..c421a59
--- /dev/null
+++ b/test/w3c/lua/test298.scxml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!-- reference a non-existent data model location in param in donedata and see that the right error is raised -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event="*" target="fail"/>
+ <state id="s01">
+ <transition target="s02"/>
+ </state>
+ <final id="s02">
+ <donedata>
+ <param location="" name="testvar3"/>
+ </donedata>
+ </final>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test301.scxml b/test/w3c/lua/test301.scxml
new file mode 100644
index 0000000..39aed2e
--- /dev/null
+++ b/test/w3c/lua/test301.scxml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- the processor should reject this document because it can't download the script.
+Therefore we fail if it runs at all. This test is valid only for datamodels that support scripting -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0">
+ <script src="-badfile-"/>
+ <state id="s0">
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test302.scxml b/test/w3c/lua/test302.scxml
new file mode 100644
index 0000000..d004690
--- /dev/null
+++ b/test/w3c/lua/test302.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that a script is evaluated at load time. <conf:script> shoudl assign the value 1 to
+Var1. Hence, if script is evaluated at download time, Var1 has a value in the initial state s0.
+This test is valid only for datamodels that support scripting -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <script>testvar1 = 1</script>
+ <state id="s0">
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test303.scxml b/test/w3c/lua/test303.scxml
new file mode 100644
index 0000000..88f79b0
--- /dev/null
+++ b/test/w3c/lua/test303.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- to test that scripts are run as part of executable content, we check that it changes the value of a var at the
+right point. This test is valid only for datamodels that support scripting -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="2" location="testvar1"/>
+ <script>testvar1 = 1</script>
+ </onentry>
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test304.scxml b/test/w3c/lua/test304.scxml
new file mode 100644
index 0000000..2022f50
--- /dev/null
+++ b/test/w3c/lua/test304.scxml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that a variable declared by a script can be accessed like any other part of the data model -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <script>testvar1 = 1</script>
+ <state id="s0">
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test307.scxml b/test/w3c/lua/test307.scxml
new file mode 100644
index 0000000..3663d5f
--- /dev/null
+++ b/test/w3c/lua/test307.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" binding="late">
+ <!-- with binding=late, in s0 we access a variable that isn't created until we get to s1. Then in s1
+we access a non-existent substructure of a variable. We use log tags to report the values that both operations
+yield, and whether there are errors. This is a manual test, since the tester must report whether the output
+is the same in the two cases -->
+ <state id="s0">
+ <onentry>
+ <log label="entering s0 value of Var 1 is: " expr="testvar1"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error" target="s1">
+ <log label="error in state s0" expr="_event"/>
+ </transition>
+ <transition event="foo" target="s1">
+ <log label="no error in s0" expr=""/>
+ </transition>
+ </state>
+ <state id="s1">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <onentry>
+ <log label="entering s1, value of non-existent substructure of Var 1 is: " expr="testvar1.nonono"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition event="error" target="final">
+ <log label="error in state s1" expr="_event"/>
+ </transition>
+ <transition event="bar" target="final">
+ <log label="No error in s1" expr=""/>
+ </transition>
+ </state>
+ <final id="final"/>
+</scxml>
diff --git a/test/w3c/lua/test309.scxml b/test/w3c/lua/test309.scxml
new file mode 100644
index 0000000..8a9195c
--- /dev/null
+++ b/test/w3c/lua/test309.scxml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that an expression that cannot be interpreted as a boolean is treated as false -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0">
+ <transition cond="@@@@@@@@@@@@@@@@" target="fail"/>
+ <transition target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test310.scxml b/test/w3c/lua/test310.scxml
new file mode 100644
index 0000000..89297af
--- /dev/null
+++ b/test/w3c/lua/test310.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- simple test of the in() predicate -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="p" datamodel="lua">
+ <parallel id="p">
+ <state id="s0">
+ <transition cond="In('s1')" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1"/>
+ </parallel>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test311.scxml b/test/w3c/lua/test311.scxml
new file mode 100644
index 0000000..4eab475
--- /dev/null
+++ b/test/w3c/lua/test311.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that assignment to a non-existent location yields an error -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ <assign expr="1" location=""/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event=".*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test312.scxml b/test/w3c/lua/test312.scxml
new file mode 100644
index 0000000..7207dbe
--- /dev/null
+++ b/test/w3c/lua/test312.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that assignment with an illegal expr raises an error -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="!" location="testvar1"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event=".*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test313.scxml b/test/w3c/lua/test313.scxml
new file mode 100644
index 0000000..7045cda
--- /dev/null
+++ b/test/w3c/lua/test313.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- this is a manual test. The processor is allowed to reject this doc, but if it executes it with its illegal
+expression, it must raise an error -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign expr="!" location="testvar1"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event=".*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test314.scxml b/test/w3c/lua/test314.scxml
new file mode 100644
index 0000000..d914420
--- /dev/null
+++ b/test/w3c/lua/test314.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- this is a manual test because the processor is allowed to reject this document. But if it executes it,
+it should not raise an error until it gets to s03 and evaluates the illegal expr -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="s01">
+ <transition event="error.execution" target="fail"/>
+ <state id="s01">
+ <transition target="s02"/>
+ </state>
+ <state id="s02">
+ <transition target="s03"/>
+ </state>
+ <state id="s03">
+ <onentry>
+ <assign expr="!" location="testvar1"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event=".*" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test318.scxml b/test/w3c/lua/test318.scxml
new file mode 100644
index 0000000..dc2c885
--- /dev/null
+++ b/test/w3c/lua/test318.scxml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that _event stays bound during the onexit and entry into the next state -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="foo" target="s1"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <raise event="bar"/>
+ <!-- _event should still be bound to 'foo' at this point -->
+ <assign expr="_event.name" location="testvar1"/>
+ </onentry>
+ <transition cond="testvar1 == 'foo'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test319.scxml b/test/w3c/lua/test319.scxml
new file mode 100644
index 0000000..06ac189
--- /dev/null
+++ b/test/w3c/lua/test319.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that _event is not bound before any event has been raised -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <if cond="_event ~= nil">
+ <raise event="bound"/>
+ <else/>
+ <raise event="unbound"/>
+ </if>
+ </onentry>
+ <transition event="unbound" target="pass"/>
+ <transition event="bound" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test321.scxml b/test/w3c/lua/test321.scxml
new file mode 100644
index 0000000..b141cd2
--- /dev/null
+++ b/test/w3c/lua/test321.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that _sessionid is bound on startup -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data expr="_sessionid" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="testvar1 ~= nil" target="pass"/>
+ <transition cond="true" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test322.scxml b/test/w3c/lua/test322.scxml
new file mode 100644
index 0000000..49e5b6e
--- /dev/null
+++ b/test/w3c/lua/test322.scxml
@@ -0,0 +1,26 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that _sessionid remains bound to the same value throught the session. this means that it can't
+be assigned to -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data expr="_sessionid" id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <transition target="s1"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <assign expr="'otherName'" location="_sessionid"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="s2"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s2">
+ <transition cond="testvar1 == _sessionid" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test323.scxml b/test/w3c/lua/test323.scxml
new file mode 100644
index 0000000..1233bc5
--- /dev/null
+++ b/test/w3c/lua/test323.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that _name is bound on startup -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data expr="_name" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="testvar1 ~= nil" target="pass"/>
+ <transition cond="true" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test324.scxml b/test/w3c/lua/test324.scxml
new file mode 100644
index 0000000..1222cee
--- /dev/null
+++ b/test/w3c/lua/test324.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that _name stays bound till the session ends. This means that it cannot be assigned to -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <transition target="s1" cond="_name == 'machineName'"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <assign expr="'otherName'" location="_name"/>
+ </onentry>
+ <transition cond="_name == 'machineName'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test325.scxml b/test/w3c/lua/test325.scxml
new file mode 100644
index 0000000..b61d2e1
--- /dev/null
+++ b/test/w3c/lua/test325.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that _ioprocessors is bound at startup. I'm not sure how to test for a set value or
+how to test that the entries in it do represent I/O processors, since the set that each implementation
+supports may be different. Suggestions welcome -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data expr="_ioprocessors" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="testvar1 ~= nil" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test326.scxml b/test/w3c/lua/test326.scxml
new file mode 100644
index 0000000..c6d3a17
--- /dev/null
+++ b/test/w3c/lua/test326.scxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that _ioprocessors stays bound till the session ends. This means that it cannot be assigned to -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data expr="_ioprocessors" id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <transition target="s1" cond="testvar1 ~= nil"/>
+ <transition cond="true" target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <assign expr="'otherName'" location="_ioprocessors"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="s2"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s2">
+ <onentry>
+ <assign expr="_ioprocessors" location="testvar2"/>
+ </onentry>
+ <transition cond="testvar1 == testvar2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test329.scxml b/test/w3c/lua/test329.scxml
new file mode 100644
index 0000000..6f2f0a0
--- /dev/null
+++ b/test/w3c/lua/test329.scxml
@@ -0,0 +1,46 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that none of the system variables can be modified -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ <data id="testvar2"/>
+ <data id="testvar3"/>
+ <data id="testvar4"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <!-- get _event bound so we can use it in s1-->
+ <raise event="foo"/>
+ <assign expr="_sessionid" location="testvar1"/>
+ <assign expr="-1" location="_sessionid"/>
+ </onentry>
+ <transition event="foo" target="s1" cond="testvar1 == _sessionid"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <assign expr="_event" location="testvar2"/>
+ <assign expr="27" location="_event"/>
+ </onentry>
+ <transition target="s2" cond="testvar2 == _event"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s2">
+ <onentry>
+ <assign expr="_name" location="testvar3"/>
+ <assign expr="27" location="_name"/>
+ </onentry>
+ <transition target="s3" cond="testvar3 == _name"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s3">
+ <onentry>
+ <assign expr="_ioprocessors" location="testvar4"/>
+ <assign expr="27" location="_ioprocessors"/>
+ </onentry>
+ <transition cond="testvar4 == _ioprocessors" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test330.scxml b/test/w3c/lua/test330.scxml
new file mode 100644
index 0000000..9e79f3a
--- /dev/null
+++ b/test/w3c/lua/test330.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- check that the required fields are present in both internal and external events -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="foo" target="s1" cond="_event.name~=nil and _event.type~=nil and _event.sendid~=nil and _event.origin~=nil and _event.invokeid~=nil"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <send event="foo"/>
+ </onentry>
+ <transition event="foo" cond="_event.name~=nil and _event.type~=nil and _event.sendid~=nil and _event.origin~=nil and _event.invokeid~=nil" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test331.scxml b/test/w3c/lua/test331.scxml
new file mode 100644
index 0000000..7598bf4
--- /dev/null
+++ b/test/w3c/lua/test331.scxml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" name="machineName" datamodel="lua">
+ <!-- test that _event.type is set correctly for internal, platform, and external events -->
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <!-- internal event -->
+ <raise event="foo"/>
+ </onentry>
+ <transition event="foo" target="s1">
+ <assign expr="_event.type" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition target="s2" cond="testvar1 == 'internal'"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s2">
+ <onentry>
+ <!-- this will generate an error, which is a platform event -->
+ <assign expr="1" location=""/>
+ </onentry>
+ <transition event="error" target="s3">
+ <assign expr="_event.type" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s3">
+ <transition target="s4" cond="testvar1 == 'platform'"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s4">
+ <onentry>
+ <!-- external event -->
+ <send event="foo"/>
+ </onentry>
+ <transition event="foo" target="s5">
+ <assign expr="_event.type" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s5">
+ <transition cond="testvar1 == 'external'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test332.scxml b/test/w3c/lua/test332.scxml
new file mode 100644
index 0000000..ebdd390
--- /dev/null
+++ b/test/w3c/lua/test332.scxml
@@ -0,0 +1,26 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that sendid is present in error events triggered by send errors -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <!-- this will raise an error and also store the sendid in var1 -->
+ <send event="foo" idlocation="'testvar1'" target="xxxxxxxxx"/>
+ </onentry>
+ <transition event="error" target="s1">
+ <!-- get the sendid out of the error event -->
+ <assign expr="_event.sendid" location="testvar2"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <!-- make sure that the sendid in the error event matches the one generated when send executed -->
+ <transition cond="testvar1==testvar2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test333.scxml b/test/w3c/lua/test333.scxml
new file mode 100644
index 0000000..96ea4bf
--- /dev/null
+++ b/test/w3c/lua/test333.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- make sure sendid is blank in a non-error event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="foo"/>
+ </onentry>
+ <transition event="foo" cond="_event.sendid == ''" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test335.scxml b/test/w3c/lua/test335.scxml
new file mode 100644
index 0000000..d31a209
--- /dev/null
+++ b/test/w3c/lua/test335.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that origin field is blank for internal events -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="foo" cond="_event.origin == ''" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test336.scxml b/test/w3c/lua/test336.scxml
new file mode 100644
index 0000000..fe0899f
--- /dev/null
+++ b/test/w3c/lua/test336.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the origin field of an external event contains a URL that lets you send back to the originator. In
+this case it's the same session, so if we get bar we succeed -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="foo"/>
+ </onentry>
+ <transition event="foo" target="s1">
+ <send event="bar" targetexpr="_event.origin" typeexpr="_event.origintype"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <send event="baz"/>
+ </onentry>
+ <transition event="bar" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test337.scxml b/test/w3c/lua/test337.scxml
new file mode 100644
index 0000000..641838b
--- /dev/null
+++ b/test/w3c/lua/test337.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that origintype is blank on internal events -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="foo" cond="_event.origintype == ''" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test338.scxml b/test/w3c/lua/test338.scxml
new file mode 100644
index 0000000..5772da0
--- /dev/null
+++ b/test/w3c/lua/test338.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that invokeid is set correctly in events received from an invoked process. timeout event catches the
+case where the invoke doesn't work correctly -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/" idlocation="'testvar1'">
+ <content>
+ <scxml initial="sub0" version="1.0" name="machineName" datamodel="lua">
+ <final id="sub0">
+ <onentry>
+ <send target="#_parent" event="event1"/>
+ </onentry>
+ </final>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="event1" target="s1">
+ <assign expr="_event.invokeid" location="testvar2"/>
+ </transition>
+ <transition event="event0" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1==testvar2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test339.scxml b/test/w3c/lua/test339.scxml
new file mode 100644
index 0000000..3c60863
--- /dev/null
+++ b/test/w3c/lua/test339.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that invokeid is blank in an event that wasn't returned from an invoked process -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="foo" cond="_event.invokeid == ''" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test342.scxml b/test/w3c/lua/test342.scxml
new file mode 100644
index 0000000..dce833b
--- /dev/null
+++ b/test/w3c/lua/test342.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that eventexpr works and sets the name field of the resulting event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <datamodel>
+ <data expr="'foo'" id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send eventexpr="testvar1"/>
+ </onentry>
+ <transition event="foo" target="s1">
+ <assign expr="_event.name" location="testvar2"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1==testvar2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test343.scxml b/test/w3c/lua/test343.scxml
new file mode 100644
index 0000000..b8da21c
--- /dev/null
+++ b/test/w3c/lua/test343.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that illegal <param> produces error.execution and empty event.data -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <!-- we should get the error before the done event -->
+ <transition event="error.execution" target="s1"/>
+ <transition event="done.state.s0" target="fail"/>
+ <transition event="done.state.s0" target="fail">
+ </transition>
+ <state id="s01">
+ <transition target="s02"/>
+ </state>
+ <final id="s02">
+ <donedata>
+ <param name="someParam" location=""/>
+ </donedata>
+ </final>
+ </state>
+ <!-- if we get here, we received the error event. Now check that the done
+ event has empty event.data -->
+ <state id="s1">
+ <transition event="done.state.s0" cond="_event.data == nil" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test344.scxml b/test/w3c/lua/test344.scxml
new file mode 100644
index 0000000..467a824
--- /dev/null
+++ b/test/w3c/lua/test344.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that a cond expression that cannot be evaluated as a
+boolean cond expression evaluates to false and causes error.execution to be raised.
+In some languages, any valid expression/object can be converted to a boolean, so conf:nonBoolean will
+have to be mapped onto something that produces a syntax error or something similarly invalid -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0">
+ <transition cond="@@@@@@@@@@@@@@@@" target="fail"/>
+ <transition target="s1"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test346.scxml b/test/w3c/lua/test346.scxml
new file mode 100644
index 0000000..be7e2dd
--- /dev/null
+++ b/test/w3c/lua/test346.scxml
@@ -0,0 +1,46 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that any attempt to change the value of a system variable causes error.execution to be raised.
+Event1..4 are there to catch the case where the error event is not raised. In cases where it is, we have
+to dispose of eventn in the next state, hence the targetless transitions (which simply throw away the event.) -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" name="machineName" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <assign expr="'otherName'" location="_sessionid"/>
+ <raise event="event1"/>
+ </onentry>
+ <transition event="error.execution" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <assign expr="'otherName'" location="_event"/>
+ <raise event="event2"/>
+ </onentry>
+ <!-- throw out event1 if it's still around -->
+ <transition event="event1"/>
+ <transition event="error.execution" target="s2"/>
+ <!-- event1 would trigger this transition if we didn't drop it. We want this transition to have
+ a very general trigger to catch cases where the wrong error event was raised -->
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s2">
+ <onentry>
+ <assign expr="'otherName'" location="_ioprocessors"/>
+ <raise event="event3"/>
+ </onentry>
+ <transition event="event2"/>
+ <transition event="error.execution" target="s3"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s3">
+ <onentry>
+ <assign expr="'otherName'" location="_name"/>
+ <raise event="event4"/>
+ </onentry>
+ <transition event="event3"/>
+ <transition event="error.execution" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test347.scxml b/test/w3c/lua/test347.scxml
new file mode 100644
index 0000000..1f33911
--- /dev/null
+++ b/test/w3c/lua/test347.scxml
@@ -0,0 +1,36 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the scxml event I/O processor works by sending events back and forth between an invoked child
+and its parent process -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <invoke id="child" type="scxml">
+ <content>
+ <scxml initial="sub0" version="1.0" name="machineName" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" target="#_parent" event="childToParent"/>
+ </onentry>
+ <transition event="parentToChild" target="subFinal"/>
+ </state>
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <onentry>
+ <send delay="20s" event="timeout"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s01">
+ <transition event="childToParent" target="s02"/>
+ </state>
+ <state id="s02">
+ <onentry>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" target="#_child" event="parentToChild"/>
+ </onentry>
+ <transition event="done.invoke" target="pass"/>
+ <transition event="error" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test348.scxml b/test/w3c/lua/test348.scxml
new file mode 100644
index 0000000..af7c220
--- /dev/null
+++ b/test/w3c/lua/test348.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <!-- test that event param of send sets the name of the event -->
+ <state id="s0">
+ <onentry>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event"/>
+ </onentry>
+ <transition event="s0Event" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test349.scxml b/test/w3c/lua/test349.scxml
new file mode 100644
index 0000000..78a2487
--- /dev/null
+++ b/test/w3c/lua/test349.scxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that value in origin field can be used to send an event back to the sender -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event"/>
+ </onentry>
+ <transition event="s0Event" target="s2">
+ <assign expr="_event.origin" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s2">
+ <onentry>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event2" targetexpr="testvar1"/>
+ </onentry>
+ <transition event="s0Event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test350.scxml b/test/w3c/lua/test350.scxml
new file mode 100644
index 0000000..73e7ca8
--- /dev/null
+++ b/test/w3c/lua/test350.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that target value is used to decide what session to deliver the event to. A session should be
+able to send an event to itself using its own session ID as the target -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="'#_scxml_'" id="testvar1"/>
+ <data expr="_sessionid" id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="testvar1" expr="testvar1..testvar2"/>
+ <send delay="5s" event="timeout"/>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event" targetexpr="testvar1"/>
+ </onentry>
+ <transition event="s0Event" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test351.scxml b/test/w3c/lua/test351.scxml
new file mode 100644
index 0000000..e839548
--- /dev/null
+++ b/test/w3c/lua/test351.scxml
@@ -0,0 +1,39 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that sendid is set in event if present in send, blank otherwise -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ <data id="testvar2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" id="send1" event="s0Event"/>
+ </onentry>
+ <transition event="s0Event" target="s1">
+ <assign expr="_event.sendid" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail">
+ </transition>
+ </state>
+ <state id="s1">
+ <transition target="s2" cond="testvar1 == 'send1'"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s2">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send event="s0Event2"/>
+ </onentry>
+ <transition event="s0Event2" target="s3">
+ <assign expr="_event.sendid" location="testvar2"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s3">
+ <transition cond="testvar2==nil or testvar2==''" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test352.scxml b/test/w3c/lua/test352.scxml
new file mode 100644
index 0000000..ea76b20
--- /dev/null
+++ b/test/w3c/lua/test352.scxml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test the origintype is 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor' -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event"/>
+ </onentry>
+ <transition event="s0Event" target="s1">
+ <assign expr="_event.origintype" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail">
+ </transition>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1 == 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test354.scxml b/test/w3c/lua/test354.scxml
new file mode 100644
index 0000000..4acecf3
--- /dev/null
+++ b/test/w3c/lua/test354.scxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that event.data can be populated using both namelist, param and <content>
+and that correct values are used -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ <data id="testvar2"/>
+ <data id="testvar3"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" namelist="testvar1">
+ <param name="param1" expr="2"/>
+ </send>
+ </onentry>
+ <transition event="event1" target="s1">
+ <assign expr="_event.data.testvar1" location="testvar2"/>
+ <assign expr="_event.data.param1" location="testvar3"/>
+ </transition>
+ <transition event="*" target="fail">
+ </transition>
+ </state>
+ <state id="s1">
+ <transition target="s2" cond="testvar2 == 1"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s2">
+ <transition target="s3" cond="testvar3 == 2"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s3">
+ <onentry>
+ <send delay="5s" event="timeout"/>
+ <send event="event2">
+ <content>foo</content>
+ </send>
+ </onentry>
+ <transition event="event2" cond="_event.data == 'foo'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test355.scxml b/test/w3c/lua/test355.scxml
new file mode 100644
index 0000000..914f9f4
--- /dev/null
+++ b/test/w3c/lua/test355.scxml
@@ -0,0 +1,12 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that default initial state is first in document order. If we enter s0 first we succeed, if s1, failure. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="lua">
+ <state id="s0">
+ <transition target="pass"/>
+ </state>
+ <state id="s1">
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test364.scxml b/test/w3c/lua/test364.scxml
new file mode 100644
index 0000000..94d86bb
--- /dev/null
+++ b/test/w3c/lua/test364.scxml
@@ -0,0 +1,71 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that default initial states are entered when a compound state is entered. First we test
+the 'initial' attribute, then the initial element, then default to the first child in document order.
+If we get to s01111 we succeed, if any other state, failure. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s1" version="1.0" datamodel="lua">
+ <state id="s1" initial="s11p112 s11p122">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s11" initial="s111">
+ <state id="s111"/>
+ <parallel id="s11p1">
+ <state id="s11p11" initial="s11p111">
+ <state id="s11p111"/>
+ <state id="s11p112">
+ <onentry>
+ <raise event="In-s11p112"/>
+ </onentry>
+ </state>
+ </state>
+ <state id="s11p12" initial="s11p121">
+ <state id="s11p121"/>
+ <state id="s11p122">
+ <transition event="In-s11p112" target="s2"/>
+ </state>
+ </state>
+ </parallel>
+ </state>
+ </state>
+ <state id="s2">
+ <initial>
+ <transition target="s21p112 s21p122"/>
+ </initial>
+ <transition event="timeout" target="fail"/>
+ <state id="s21" initial="s211">
+ <state id="s211"/>
+ <parallel id="s21p1">
+ <state id="s21p11" initial="s21p111">
+ <state id="s21p111"/>
+ <state id="s21p112">
+ <onentry>
+ <raise event="In-s21p112"/>
+ </onentry>
+ </state>
+ </state>
+ <state id="s21p12" initial="s21p121">
+ <state id="s21p121"/>
+ <state id="s21p122">
+ <transition event="In-s21p112" target="s3"/>
+ </state>
+ </state>
+ </parallel>
+ </state>
+ </state>
+ <state id="s3">
+ <transition target="fail"/>
+ <state id="s31">
+ <state id="s311">
+ <state id="s3111">
+ <transition target="pass"/>
+ </state>
+ <state id="s3112"/>
+ <state id="s312"/>
+ <state id="s32"/>
+ </state>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test372.scxml b/test/w3c/lua/test372.scxml
new file mode 100644
index 0000000..9a04396
--- /dev/null
+++ b/test/w3c/lua/test372.scxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that entering a final state generates done.state.parentid after executing the onentry elements.
+Var1 should be set to 2 (but not 3) by the time the event is raised -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="s0final">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="done.state.s0" cond="testvar1 == 2" target="pass"/>
+ <transition event="*" target="fail"/>
+ <final id="s0final">
+ <onentry>
+ <assign expr="2" location="testvar1"/>
+ </onentry>
+ <onexit>
+ <assign expr="3" location="testvar1"/>
+ </onexit>
+ </final>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test375.scxml b/test/w3c/lua/test375.scxml
new file mode 100644
index 0000000..aee863e
--- /dev/null
+++ b/test/w3c/lua/test375.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that onentry handlers are executed in document order. event1 should be raised before event2 -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <raise event="event1"/>
+ </onentry>
+ <onentry>
+ <raise event="event2"/>
+ </onentry>
+ <transition event="event1" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test376.scxml b/test/w3c/lua/test376.scxml
new file mode 100644
index 0000000..d0f6911
--- /dev/null
+++ b/test/w3c/lua/test376.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that each onentry handler is a separate block. The <send> of event1 will cause an error but
+ the increment to var1 should happen anyways -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="event1" target="xxxxxxxxx"/>
+ </onentry>
+ <onentry>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onentry>
+ <transition cond="testvar1 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test377.scxml b/test/w3c/lua/test377.scxml
new file mode 100644
index 0000000..f5bd0b0
--- /dev/null
+++ b/test/w3c/lua/test377.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that onexit handlers are executed in document order. event1 should be raised before event2 -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onexit>
+ <raise event="event1"/>
+ </onexit>
+ <onexit>
+ <raise event="event2"/>
+ </onexit>
+ <transition target="s1"/>
+ </state>
+ <state id="s1">
+ <transition event="event1" target="s2"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s2">
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test378.scxml b/test/w3c/lua/test378.scxml
new file mode 100644
index 0000000..56ea4da
--- /dev/null
+++ b/test/w3c/lua/test378.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that each onexithandler is a separate block. The <send> of event1 will cause an error but
+ the increment to var1 should happen anyways -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onexit>
+ <send event="event1" target="xxxxxxxxx"/>
+ </onexit>
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ <transition target="s1"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test387.scxml b/test/w3c/lua/test387.scxml
new file mode 100644
index 0000000..7ea485f
--- /dev/null
+++ b/test/w3c/lua/test387.scxml
@@ -0,0 +1,85 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the default history state works correctly. From initial state s3 we take a transition to s0's default
+shallow history state. That should generate "enteringS011", which takes us to s4. In s4, we
+transition to s1's default deep history state. We should end up in s122, generating "enteringS122". Otherwise failure.-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s3" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <transition event="enteringS011" target="s4"/>
+ <transition event="*" target="fail"/>
+ <history type="shallow" id="s0HistShallow">
+ <transition target="s01"/>
+ </history>
+ <history type="deep" id="s0HistDeep">
+ <transition target="s022"/>
+ </history>
+ <state id="s01" initial="s011">
+ <state id="s011">
+ <onentry>
+ <raise event="enteringS011"/>
+ </onentry>
+ </state>
+ <state id="s012">
+ <onentry>
+ <raise event="enteringS012"/>
+ </onentry>
+ </state>
+ </state>
+ <state id="s02" initial="s021">
+ <state id="s021">
+ <onentry>
+ <raise event="enteringS021"/>
+ </onentry>
+ </state>
+ <state id="s022">
+ <onentry>
+ <raise event="enteringS022"/>
+ </onentry>
+ </state>
+ </state>
+ </state>
+ <state id="s1" initial="s11">
+ <transition event="enteringS122" target="pass"/>
+ <transition event="*" target="fail"/>
+ <history type="shallow" id="s1HistShallow">
+ <transition target="s11"/>
+ </history>
+ <history type="deep" id="s1HistDeep">
+ <transition target="s122"/>
+ </history>
+ <state id="s11" initial="s111">
+ <state id="s111">
+ <onentry>
+ <raise event="enteringS111"/>
+ </onentry>
+ </state>
+ <state id="s112">
+ <onentry>
+ <raise event="enteringS112"/>
+ </onentry>
+ </state>
+ </state>
+ <state id="s12" initial="s121">
+ <state id="s121">
+ <onentry>
+ <raise event="enteringS121"/>
+ </onentry>
+ </state>
+ <state id="s122">
+ <onentry>
+ <raise event="enteringS122"/>
+ </onentry>
+ </state>
+ </state>
+ </state>
+ <state id="s3">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition target="s0HistShallow"/>
+ </state>
+ <state id="s4">
+ <transition target="s1HistDeep"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test388.scxml b/test/w3c/lua/test388.scxml
new file mode 100644
index 0000000..35bd399
--- /dev/null
+++ b/test/w3c/lua/test388.scxml
@@ -0,0 +1,66 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that history states works correctly. The counter Var1 counts how many times
+we have entered s0. The initial state is s012. We then transition to s1, which transitions
+to s0's deep history state. entering.s012 should be raised, otherwise failure. Then we transition
+to s02, which transitions to s0's shallow history state. That should have value s01, and its initial
+state is s011, so we should get entering.s011, otherwise failure.-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s012" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="s01">
+ <onentry>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onentry>
+ <!-- the first time through, go to s1, setting a timer just in case something hangs -->
+ <transition event="entering.s012" target="s1" cond="testvar1 == 1">
+ <send event="timeout" delay="2s"/>
+ </transition>
+ <!-- the second time, we should get entering.s012. If so, go to s2, otherwise fail -->
+ <transition event="entering.s012" target="s2" cond="testvar1 == 2"/>
+ <transition event="entering" cond="testvar1 == 2" target="fail"/>
+ <!-- the third time we should get entering-s011. If so, pass, otherwise fail -->
+ <transition event="entering.s011" cond="testvar1 == 3" target="pass"/>
+ <transition event="entering" cond="testvar1 == 3" target="fail"/>
+ <!-- if we timeout, the state machine is hung somewhere, so fail -->
+ <transition event="timeout" target="fail"/>
+ <history type="shallow" id="s0HistShallow">
+ <transition target="s02"/>
+ </history>
+ <history type="deep" id="s0HistDeep">
+ <transition target="s022"/>
+ </history>
+ <state id="s01" initial="s011">
+ <state id="s011">
+ <onentry>
+ <raise event="entering.s011"/>
+ </onentry>
+ </state>
+ <state id="s012">
+ <onentry>
+ <raise event="entering.s012"/>
+ </onentry>
+ </state>
+ </state>
+ <state id="s02" initial="s021">
+ <state id="s021">
+ <onentry>
+ <raise event="entering.s021"/>
+ </onentry>
+ </state>
+ <state id="s022">
+ <onentry>
+ <raise event="entering.s022"/>
+ </onentry>
+ </state>
+ </state>
+ </state>
+ <state id="s1">
+ <transition target="s0HistDeep"/>
+ </state>
+ <state id="s2">
+ <transition target="s0HistShallow"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test396.scxml b/test/w3c/lua/test396.scxml
new file mode 100644
index 0000000..1b042a2
--- /dev/null
+++ b/test/w3c/lua/test396.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the value in _event.name matches the event name used to match against transitions -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="foo" cond="_event.name == 'foo'" target="pass"/>
+ <transition event="foo" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test399.scxml b/test/w3c/lua/test399.scxml
new file mode 100644
index 0000000..5771fb7
--- /dev/null
+++ b/test/w3c/lua/test399.scxml
@@ -0,0 +1,57 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the event name matching works correctly, including prefix matching and the fact
+that the event attribute of transition may contain multiple event designators. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <!-- this will catch the failure case -->
+ <transition event="timeout" target="fail"/>
+ <state id="s01">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <!-- test that an event can match against a transition with multiple descriptors -->
+ <transition event="foo bar" target="s02"/>
+ </state>
+ <state id="s02">
+ <onentry>
+ <raise event="bar"/>
+ </onentry>
+ <!-- test that an event can match the second descriptor as well -->
+ <transition event="foo bar" target="s03"/>
+ </state>
+ <state id="s03">
+ <onentry>
+ <raise event="foo.zoo"/>
+ </onentry>
+ <!-- test that a prefix descriptor matches -->
+ <transition event="foo bar" target="s04"/>
+ </state>
+ <state id="s04">
+ <onentry>
+ <raise event="foos"/>
+ </onentry>
+ <!-- test that only token prefixes match -->
+ <transition event="foo" target="fail"/>
+ <transition event="foos" target="s05"/>
+ </state>
+ <state id="s05">
+ <onentry>
+ <raise event="foo.zoo"/>
+ </onentry>
+ <!-- test that .* works at the end of a descriptor -->
+ <transition event="foo.*" target="s06"/>
+ </state>
+ <state id="s06">
+ <onentry>
+ <raise event="foo"/>
+ </onentry>
+ <!-- test that "*" works by itself -->
+ <transition event="*" target="pass"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test401.scxml b/test/w3c/lua/test401.scxml
new file mode 100644
index 0000000..f068ac9
--- /dev/null
+++ b/test/w3c/lua/test401.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that errors go in the internal event queue. We send ourselves an external event foo, then perform
+and operation that raises an error. Then check that the error event is processed first, even though
+it was raised second -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="foo"/>
+ <!-- assigning to a non-existent location should raise an error -->
+ <assign expr="2" location=""/>
+ </onentry>
+ <transition event="foo" target="fail"/>
+ <transition event="error" target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test402.scxml b/test/w3c/lua/test402.scxml
new file mode 100644
index 0000000..11ce8ea
--- /dev/null
+++ b/test/w3c/lua/test402.scxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" standalone="no"?>
+<!-- the assertion that errors are 'like any other event' is pretty broad, but we can check that they
+are pulled off the internal queue in order, and that prefix matching works on them. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <!-- catch the failure case -->
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s01">
+ <onentry>
+ <!-- the first internal event. The error will be the second, and event2 will be the third -->
+ <raise event="event1"/>
+ <!-- assigning to a non-existent location should raise an error -->
+ <assign expr="2" location=""/>
+ </onentry>
+ <transition event="event1" target="s02">
+ <raise event="event2"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s02">
+ <transition event="error" target="s03"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s03">
+ <transition event="event2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test403a.scxml b/test/w3c/lua/test403a.scxml
new file mode 100644
index 0000000..767197f
--- /dev/null
+++ b/test/w3c/lua/test403a.scxml
@@ -0,0 +1,38 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test one part of 'optimal enablement' meaning that of all transitions that are enabled, we chose the ones
+in child states over parent states, and use document order to break ties. We have
+a parent state s0 with two children, s01 and s02. In s01, we test that a) if
+a transition in the child matches, we don't consider matches in the parent and b)
+that if two transitions match in any state, we take the first in document order.
+In s02 we test that we take a transition in the parent if there is no
+matching transition in the child. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <!-- catch the failure case -->
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <transition event="event1" target="fail"/>
+ <transition event="event2" target="pass"/>
+ <state id="s01">
+ <onentry>
+ <!-- this should be caught by the first transition in this state, taking us to S02 -->
+ <raise event="event1"/>
+ </onentry>
+ <transition event="event1" target="s02"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s02">
+ <onentry>
+ <!-- since the local transition has a cond that evaluates to false this should be caught by a
+ transition in the parent state, taking us to pass -->
+ <raise event="event2"/>
+ </onentry>
+ <transition event="event1" target="fail"/>
+ <transition event="event2" cond="false" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test403b.scxml b/test/w3c/lua/test403b.scxml
new file mode 100644
index 0000000..2de4d9a
--- /dev/null
+++ b/test/w3c/lua/test403b.scxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that 'optimally enabled set' really is a set, specifically that if a transition is optimally enabled in
+two different states, it is taken only once. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="p0">
+ <!-- this transition should never be taken because a transition in a lower state should
+ always be selected -->
+ <transition event="event1">
+ <assign location="testvar1" expr="testvar1+1"/>
+ </transition>
+ <parallel id="p0">
+ <onentry>
+ <raise event="event1"/>
+ <raise event="event2"/>
+ </onentry>
+ <!-- this transition will be selected by both states p0s1 and p0s2, but should be executed only once -->
+ <transition event="event1">
+ <assign location="testvar1" expr="testvar1+1"/>
+ </transition>
+ <state id="p0s1">
+ <transition event="event2" cond="testvar1 == 1" target="pass"/>
+ <transition event="event2" target="fail"/>
+ </state>
+ <state id="p0s2"/>
+ </parallel>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test403c.scxml b/test/w3c/lua/test403c.scxml
new file mode 100644
index 0000000..200e0ff
--- /dev/null
+++ b/test/w3c/lua/test403c.scxml
@@ -0,0 +1,45 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test 'optimally enabled set', specifically that preemption works correctly -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0" initial="p0">
+ <onentry>
+ <raise event="event1"/>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="event2" target="fail"/>
+ <transition event="timeout" target="fail"/>
+ <parallel id="p0">
+ <state id="p0s1">
+ <transition event="event1"/>
+ <transition event="event2"/>
+ </state>
+ <state id="p0s2">
+ <transition event="event1" target="p0s1">
+ <raise event="event2"/>
+ </transition>
+ </state>
+ <state id="p0s3">
+ <!-- this transition should be blocked by the one in p0s2-->
+ <transition event="event1" target="fail"/>
+ <!-- this transition will preempt the one that p0s2 inherits
+ from an ancestor -->
+ <transition event="event2" target="s1"/>
+ </state>
+ <state id="p0s4">
+ <!-- this transition never gets preempted, should fire twice -->
+ <transition event="*">
+ <assign location="testvar1" expr="testvar1+1"/>
+ </transition>
+ </state>
+ </parallel>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test404.scxml b/test/w3c/lua/test404.scxml
new file mode 100644
index 0000000..8803483
--- /dev/null
+++ b/test/w3c/lua/test404.scxml
@@ -0,0 +1,48 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that states are exited in exit order (children before parents with reverse doc order used to break ties
+ before the executable content in the transitions. event1, event2, event3, event4 should be raised in that
+ order when s01p is exited -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01p">
+ <parallel id="s01p">
+ <onexit>
+ <!-- this should be the 3rd event raised -->
+ <raise event="event3"/>
+ </onexit>
+ <transition target="s02">
+ <!-- this should be the fourth event raised -->
+ <raise event="event4"/>
+ </transition>
+ <state id="s01p1">
+ <onexit>
+ <!-- this should be the second event raised -->
+ <raise event="event2"/>
+ </onexit>
+ </state>
+ <state id="s01p2">
+ <!-- this should be the first event raised -->
+ <onexit>
+ <raise event="event1"/>
+ </onexit>
+ </state>
+ </parallel>
+ <state id="s02">
+ <transition event="event1" target="s03"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s03">
+ <transition event="event2" target="s04"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s04">
+ <transition event="event3" target="s05"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s05">
+ <transition event="event4" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test405.scxml b/test/w3c/lua/test405.scxml
new file mode 100644
index 0000000..54dde5f
--- /dev/null
+++ b/test/w3c/lua/test405.scxml
@@ -0,0 +1,58 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the executable content in the transitions is executed in document order after
+the states are exited. event1, event2, event3, event4 should be raised in that order when the
+state machine is entered -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01p">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <parallel id="s01p">
+ <transition event="event1" target="s02"/>
+ <state id="s01p1" initial="s01p11">
+ <state id="s01p11">
+ <onexit>
+ <!-- this should be the second event raised -->
+ <raise event="event2"/>
+ </onexit>
+ <transition target="s01p12">
+ <!-- this should be the third event raised -->
+ <raise event="event3"/>
+ </transition>
+ </state>
+ <state id="s01p12"/>
+ </state>
+ <!-- end s01p1 -->
+ <state id="s01p2" initial="s01p21">
+ <state id="s01p21">
+ <onexit>
+ <!-- this should be the first event raised -->
+ <raise event="event1"/>
+ </onexit>
+ <transition target="s01p22">
+ <!-- this should be the fourth event raised -->
+ <raise event="event4"/>
+ </transition>
+ </state>
+ <state id="s01p22"/>
+ </state>
+ <!-- end s01p2 -->
+ </parallel>
+ <state id="s02">
+ <transition event="event2" target="s03"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s03">
+ <transition event="event3" target="s04"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s04">
+ <transition event="event4" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ </state>
+ <!-- end s01 -->
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test406.scxml b/test/w3c/lua/test406.scxml
new file mode 100644
index 0000000..eb4fa7b
--- /dev/null
+++ b/test/w3c/lua/test406.scxml
@@ -0,0 +1,52 @@
+<?xml version="1.0" standalone="no"?>
+<!-- Test that states are entered in entry order (parents before children with document order used to break ties)
+after the executable content in the transition is executed. event1, event2, event3, event4 should be raised in that
+order when the transition in s01 is taken -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s01">
+ <transition target="s0p2">
+ <!-- this should be the first event raised -->
+ <raise event="event1"/>
+ </transition>
+ </state>
+ <parallel id="s0p2">
+ <transition event="event1" target="s03"/>
+ <state id="s01p21">
+ <onentry>
+ <!-- third event -->
+ <raise event="event3"/>
+ </onentry>
+ </state>
+ <state id="s01p22">
+ <onentry>
+ <!-- the fourth event -->
+ <raise event="event4"/>
+ </onentry>
+ </state>
+ <onentry>
+ <!-- this should be the second event raised -->
+ <raise event="event2"/>
+ </onentry>
+ </parallel>
+ <state id="s03">
+ <transition event="event2" target="s04"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s04">
+ <transition event="event3" target="s05"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s05">
+ <transition event="event4" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ </state>
+ <!-- end s0 -->
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test407.scxml b/test/w3c/lua/test407.scxml
new file mode 100644
index 0000000..2b459d8
--- /dev/null
+++ b/test/w3c/lua/test407.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- a simple test that onexit handlers work. var1 should be incremented when we leave s0 -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ <transition target="s1"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test409.scxml b/test/w3c/lua/test409.scxml
new file mode 100644
index 0000000..ccf9d73
--- /dev/null
+++ b/test/w3c/lua/test409.scxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that states are removed from the active states list as they are exited. When s01's onexit handler
+fires, s011 should not be on the active state list, so in(S011) should be false, and event1 should not
+be raised. Therefore the timeout should fire to indicate success -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="100ms"/>
+ </onentry>
+ <transition event="timeout" target="pass"/>
+ <transition event="event1" target="fail"/>
+ <state id="s01" initial="s011">
+ <onexit>
+ <if cond="In('s011')">
+ <raise event="event1"/>
+ </if>
+ </onexit>
+ <state id="s011">
+ <transition target="s02"/>
+ </state>
+ </state>
+ <!-- end s01 -->
+ <state id="s02"/>
+ </state>
+ <!-- end s0 -->
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test411.scxml b/test/w3c/lua/test411.scxml
new file mode 100644
index 0000000..7cec20a
--- /dev/null
+++ b/test/w3c/lua/test411.scxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that states are added to the active states list as they are entered and before onentry handlers
+are executed. When s0's onentry handler fires we should not be in s01. But when s01's onentry handler
+fires, we should be in s01. Therefore event1 should not fire, but event2 should. Either event1 or
+timeout also indicates failure -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ <if cond="In('s01')">
+ <raise event="event1"/>
+ </if>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <transition event="event1" target="fail"/>
+ <transition event="event2" target="pass"/>
+ <state id="s01">
+ <onentry>
+ <if cond="In('s01')">
+ <raise event="event2"/>
+ </if>
+ </onentry>
+ </state>
+ </state>
+ <!-- end s0 -->
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test412.scxml b/test/w3c/lua/test412.scxml
new file mode 100644
index 0000000..a55514b
--- /dev/null
+++ b/test/w3c/lua/test412.scxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that executable content in the <initial> transition executes after the onentry handler on the state
+and before the onentry handler of the child states. Event1, event2, and event3 should occur in that order. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <transition event="event1" target="fail"/>
+ <transition event="event2" target="pass"/>
+ <state id="s01">
+ <onentry>
+ <raise event="event1"/>
+ </onentry>
+ <initial>
+ <transition target="s011">
+ <raise event="event2"/>
+ </transition>
+ </initial>
+ <state id="s011">
+ <onentry>
+ <raise event="event3"/>
+ </onentry>
+ <transition target="s02"/>
+ </state>
+ </state>
+ <state id="s02">
+ <transition event="event1" target="s03"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s03">
+ <transition event="event2" target="s04"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s04">
+ <transition event="event3" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ </state>
+ <!-- end s0 -->
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test413.scxml b/test/w3c/lua/test413.scxml
new file mode 100644
index 0000000..7b2563b
--- /dev/null
+++ b/test/w3c/lua/test413.scxml
@@ -0,0 +1,36 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the state machine is put into the configuration specified by the initial element, without regard
+to any other defaults. we should start off in s2p111 and s2p122. the atomic
+states we should not enter all have immediate transitions to failure in them -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s2p112 s2p122" version="1.0" datamodel="lua">
+ <state id="s1">
+ <transition target="fail"/>
+ </state>
+ <state id="s2" initial="s2p1">
+ <parallel id="s2p1">
+ <!-- this transition will be triggered only if we end up in an illegal configuration where we're in
+ either s2p112 or s2p122, but not both of them -->
+ <transition target="fail"/>
+ <state id="s2p11" initial="s2p111">
+ <state id="s2p111">
+ <transition target="fail"/>
+ </state>
+ <state id="s2p112">
+ <transition cond="In('s2p122')" target="pass"/>
+ </state>
+ </state>
+ <!-- end s2p11 -->
+ <state id="s2p12" initial="s2p121">
+ <state id="s2p121">
+ <transition target="fail"/>
+ </state>
+ <state id="s2p122">
+ <transition cond="In('s2p112')" target="pass"/>
+ </state>
+ </state>
+ </parallel>
+ </state>
+ <!-- end s2 -->
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test415.scxml b/test/w3c/lua/test415.scxml
new file mode 100644
index 0000000..c2e883a
--- /dev/null
+++ b/test/w3c/lua/test415.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- Test that the state machine halts when it enters a top-level final state. Since
+ the initial state is a final state, this machine should halt immediately without
+ processing "event1" which is raised in the final state's on-entry handler. This
+ is a manual test since there is no platform-independent way to test that event1
+ is not processed -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="final" version="1.0" datamodel="lua">
+ <final id="final">
+ <onentry>
+ <raise event="event1"/>
+ </onentry>
+ </final>
+</scxml>
diff --git a/test/w3c/lua/test416.scxml b/test/w3c/lua/test416.scxml
new file mode 100644
index 0000000..b3ba383
--- /dev/null
+++ b/test/w3c/lua/test416.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the done.state.id gets generated when we enter the final state of a compound state -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s1" datamodel="lua">
+ <state id="s1" initial="s11">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s11" initial="s111">
+ <transition event="done.state.s11" target="pass"/>
+ <state id="s111">
+ <transition target="s11final"/>
+ </state>
+ <final id="s11final"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test417.scxml b/test/w3c/lua/test417.scxml
new file mode 100644
index 0000000..5a500f7
--- /dev/null
+++ b/test/w3c/lua/test417.scxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that we get the done.state.id event when all of a
+parallel elements children enter final states. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s1" datamodel="lua">
+ <state id="s1" initial="s1p1">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <parallel id="s1p1">
+ <transition event="done.state.s1p1" target="pass"/>
+ <state id="s1p11" initial="s1p111">
+ <state id="s1p111">
+ <transition target="s1p11final"/>
+ </state>
+ <final id="s1p11final"/>
+ </state>
+ <state id="s1p12" initial="s1p121">
+ <state id="s1p121">
+ <transition target="s1p12final"/>
+ </state>
+ <final id="s1p12final"/>
+ </state>
+ </parallel>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test419.scxml b/test/w3c/lua/test419.scxml
new file mode 100644
index 0000000..1043b31
--- /dev/null
+++ b/test/w3c/lua/test419.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that eventless transitions take precedence over event-driven ones -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s1" datamodel="lua">
+ <state id="s1">
+ <onentry>
+ <raise event="internalEvent"/>
+ <send event="externalEvent"/>
+ </onentry>
+ <transition event="*" target="fail"/>
+ <transition target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test421.scxml b/test/w3c/lua/test421.scxml
new file mode 100644
index 0000000..358d260
--- /dev/null
+++ b/test/w3c/lua/test421.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that internal events take priority over external ones, and that the processor
+keeps pulling off internal events until it finds one that triggers a transition -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s1" datamodel="lua">
+ <state id="s1" initial="s11">
+ <onentry>
+ <send event="externalEvent"/>
+ <raise event="internalEvent1"/>
+ <raise event="internalEvent2"/>
+ <raise event="internalEvent3"/>
+ <raise event="internalEvent4"/>
+ </onentry>
+ <transition event="externalEvent" target="fail"/>
+ <state id="s11">
+ <transition event="internalEvent3" target="s12"/>
+ </state>
+ <state id="s12">
+ <transition event="internalEvent4" target="pass"/>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test422.scxml b/test/w3c/lua/test422.scxml
new file mode 100644
index 0000000..f97b3bc
--- /dev/null
+++ b/test/w3c/lua/test422.scxml
@@ -0,0 +1,73 @@
+<?xml version="1.0" standalone="no"?>
+<!-- Test that at the end of a macrostep, the processor executes all invokes in states
+that have been entered and not exited during the step. (The invokes are supposed to be executed
+in document order, but we can test that since each invocation is separate and they may take
+different amounts to time to start up.) In this case, there are three invoke statements,
+in states s1, s11 and s12. Each invoked process returns an event named after its parent state.
+The invokes in s1 and s12 should execute, but not the one
+in s11. So we should receive invokeS1, invokeS12, but not invokeS12. Furthermore, when the timeout fires, var1 should equal 2.-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s1" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s1" initial="s11">
+ <onentry>
+ <send event="timeout" delay="200ms"/>
+ </onentry>
+ <transition event="invokeS1 invokeS12">
+ <assign location="testvar1" expr="testvar1+1"/>
+ </transition>
+ <transition event="invokeS11" target="fail"/>
+ <transition event="timeout" cond="testvar1 == 2" target="pass"/>
+ <transition event="timeout" target="fail"/>
+ <invoke>
+ <content>
+ <!-- when invoked, send 'foo' to parent, then terminate. -->
+ <scxml initial="sub0" version="1.0" datamodel="lua">
+ <state id="sub0">
+ <onentry>
+ <send target="#_parent" event="invokeS1"/>
+ </onentry>
+ <transition target="subFinal0"/>
+ </state>
+ <final id="subFinal0"/>
+ </scxml>
+ </content>
+ </invoke>
+ <state id="s11">
+ <invoke>
+ <content>
+ <!-- when invoked, send 'foo' to parent, then terminate. -->
+ <scxml initial="sub1" version="1.0" datamodel="lua">
+ <state id="sub1">
+ <onentry>
+ <send target="#_parent" event="invokeS11"/>
+ </onentry>
+ <transition target="subFinal1"/>
+ </state>
+ <final id="subFinal1"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition target="s12"/>
+ </state>
+ <state id="s12">
+ <invoke>
+ <content>
+ <!-- when invoked, send 'foo' to parent, then terminate. -->
+ <scxml initial="sub2" version="1.0" datamodel="lua">
+ <state id="sub2">
+ <onentry>
+ <send target="#_parent" event="invokeS12"/>
+ </onentry>
+ <transition target="subFinal2"/>
+ </state>
+ <final id="subFinal2"/>
+ </scxml>
+ </content>
+ </invoke>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test423.scxml b/test/w3c/lua/test423.scxml
new file mode 100644
index 0000000..d083110
--- /dev/null
+++ b/test/w3c/lua/test423.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that we keep pulling external events off the queue till we find one that matches a transition. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="externalEvent1"/>
+ <send event="externalEvent2" delay="100ms"/>
+ <raise event="internalEvent"/>
+ </onentry>
+ <!-- in this state we should process only internalEvent -->
+ <transition event="internalEvent" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <!-- in this state we ignore externalEvent1 and wait for externalEvent2 -->
+ <transition event="externalEvent2" target="pass"/>
+ <transition event="internalEvent" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test436.scxml b/test/w3c/lua/test436.scxml
new file mode 100644
index 0000000..da5f5a6
--- /dev/null
+++ b/test/w3c/lua/test436.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that in() predicate works in null data model -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" datamodel="null" version="1.0" initial="p">
+ <parallel id="p">
+ <state id="ps0">
+ <transition cond="In('s1')" target="fail"/>
+ <transition cond="In('ps1')" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <state id="ps1"/>
+ </parallel>
+ <state id="s1"/>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test444.scxml b/test/w3c/lua/test444.scxml
new file mode 100644
index 0000000..2ec8b38
--- /dev/null
+++ b/test/w3c/lua/test444.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that <data> creates a new ecmascript variable. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" datamodel="ecmascript" version="1.0">
+ <datamodel>
+ <data id="var1" expr="1"/>
+ </datamodel>
+ <state id="s0">
+ <!-- test that var1 can be used as an ecmascript variable -->
+ <transition cond="++var1==2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test445.scxml b/test/w3c/lua/test445.scxml
new file mode 100644
index 0000000..2946c9d
--- /dev/null
+++ b/test/w3c/lua/test445.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that ecmascript objects defined by <data> have value undefined if <data> does not assign a value -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" datamodel="ecmascript" version="1.0">
+ <datamodel>
+ <data id="var1"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="var1==undefined" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test446.scxml b/test/w3c/lua/test446.scxml
new file mode 100644
index 0000000..79f8652
--- /dev/null
+++ b/test/w3c/lua/test446.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- in the ECMA data model, test that if the child of <data> is JSON, the processor
+ assigns it as the value of the var -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <datamodel>
+ <data id="var1">[1, 2, 3]</data>
+ <data id="var2" src="file:test446.txt"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="var1 instanceof Array" target="s1"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="var2 instanceof Array" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test446.txt b/test/w3c/lua/test446.txt
new file mode 100644
index 0000000..3a26a2e
--- /dev/null
+++ b/test/w3c/lua/test446.txt
@@ -0,0 +1 @@
+[1,2,3] \ No newline at end of file
diff --git a/test/w3c/lua/test448.scxml b/test/w3c/lua/test448.scxml
new file mode 100644
index 0000000..abe7957
--- /dev/null
+++ b/test/w3c/lua/test448.scxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that all ecmascript objects are placed in a single global scope -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" datamodel="ecmascript" version="1.0">
+ <state id="s0">
+ <!-- test that a parent state can access a variable defined in a child -->
+ <transition cond="var1==1" target="s1"/>
+ <transition target="fail"/>
+ <state id="s01">
+ <datamodel>
+ <data id="var1" expr="1"/>
+ </datamodel>
+ </state>
+ </state>
+ <state id="s1" initial="s01p">
+ <parallel id="s01p">
+ <state id="s01p1">
+ <!-- test that we can access a variable defined in a parallel sibling state -->
+ <transition cond="var2==1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s01p2">
+ <datamodel>
+ <data id="var2" expr="1"/>
+ </datamodel>
+ </state>
+ </parallel>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test449.scxml b/test/w3c/lua/test449.scxml
new file mode 100644
index 0000000..f0f1830
--- /dev/null
+++ b/test/w3c/lua/test449.scxml
@@ -0,0 +1,10 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that ecmascript objects are converted to booleans inside cond -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" datamodel="ecmascript" version="1.0">
+ <state id="s0">
+ <transition cond="'foo'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test451.scxml b/test/w3c/lua/test451.scxml
new file mode 100644
index 0000000..08f04cc
--- /dev/null
+++ b/test/w3c/lua/test451.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- simple test of the in() predicate -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="ecmascript" initial="p">
+ <parallel id="p">
+ <state id="s0">
+ <transition cond="In('s1')" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1"/>
+ </parallel>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test452.scxml b/test/w3c/lua/test452.scxml
new file mode 100644
index 0000000..2965bb0
--- /dev/null
+++ b/test/w3c/lua/test452.scxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that we can assign to any location in the datamodel. In this case, we just test that we can assign
+to a substructure (not the top level variable). This may not be the most idiomatic way to write the test -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" datamodel="ecmascript" version="1.0">
+ <datamodel>
+ <data id="foo" expr="0"/>
+ </datamodel>
+ <script>
+ function testobject() {
+ this.bar = 0;}
+ </script>
+ <state id="s0">
+ <onentry>
+ <assign location="foo" expr="new testobject();"/>
+ <!-- try to assign to foo's bar property -->
+ <assign location="foo.bar" expr="1"/>
+ <raise event="event1"/>
+ </onentry>
+ <!-- test that we have assigned to foo's bar property -->
+ <transition event="event1" cond="foo.bar == 1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test453.scxml b/test/w3c/lua/test453.scxml
new file mode 100644
index 0000000..e5337fa
--- /dev/null
+++ b/test/w3c/lua/test453.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that we can use any ecmascript expression as a value expression.
+In this case, we just test that we can assign
+a function to a variable and then call it. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" datamodel="ecmascript" version="1.0">
+ <datamodel>
+ <data id="var1" expr="function(invar) {return invar + 1;}"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <raise event="event1"/>
+ </onentry>
+ <!-- test that we can call the function -->
+ <transition event="event1" cond="var1(2) == 3" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test456.scxml b/test/w3c/lua/test456.scxml
new file mode 100644
index 0000000..319c1a4
--- /dev/null
+++ b/test/w3c/lua/test456.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we can't test that _any_ ecmascript is valid inside <script>, so we
+just run a simple one and check that it can update the data model. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <script>
+ Var1+=1
+ </script>
+ </onentry>
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test457.scxml b/test/w3c/lua/test457.scxml
new file mode 100644
index 0000000..4a7ad33
--- /dev/null
+++ b/test/w3c/lua/test457.scxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that an the legal iterable collections are arrays, namely objects that satisfy instanceof(Array) in ECMAScript.
+ the legal values for the 'item' attribute on foreach are legal ECMAScript variable names.. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" datamodel="ecmascript" version="1.0">
+ <datamodel>
+ <data id="Var1" expr="0"/>
+ <data id="Var2"/>
+ <data id="Var3"/>
+ <data id="Var4" expr="7"/>
+ <data id="Var5" expr="[1,2,3]"/>
+ <data id="Var6"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <!-- invalid array, legal item -->
+ <foreach item="Var2" index="Var3" array="Var4">
+ <assign location="Var1" expr="Var1 + 1"/>
+ </foreach>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.execution" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <!-- illegal item, legal array -->
+ <foreach item="'continue'" index="Var3" array="Var5">
+ <assign location="Var1" expr="Var1 + 1"/>
+ </foreach>
+ <raise event="bar"/>
+ </onentry>
+ <transition event="error.execution" target="s2"/>
+ <transition event="bar" target="fail"/>
+ </state>
+ <state id="s2">
+ <!-- check that var1 has its original value (so executable content never got executed -->
+ <transition cond="Var1==0" target="s3"/>
+ <transition target="fail"/>
+ </state>
+ <!-- finally check that a legal array works properly -->
+ <state id="s3">
+ <onentry>
+ <assign location="Var6" expr="0"/>
+ <foreach item="Var2" array="Var5">
+ <assign location="Var6" expr="Var6 + Var2"/>
+ </foreach>
+ </onentry>
+ <transition cond="Var6==6" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass">
+ <onentry>
+ <log label="Outcome" expr="'pass'"/>
+ </onentry>
+ </final>
+ <final id="fail">
+ <onentry>
+ <log label="Outcome" expr="'fail'"/>
+ </onentry>
+ </final>
+</scxml>
diff --git a/test/w3c/lua/test459.scxml b/test/w3c/lua/test459.scxml
new file mode 100644
index 0000000..54029a1
--- /dev/null
+++ b/test/w3c/lua/test459.scxml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that foreach goes over the array in the right order. since the array contains 1 2 3, we compare the current
+value with the previous value, which is stored in var1. The current value should always be larger. If
+it ever isn't, set Var4 to 0, indicating failure. Also check that the final value of the index
+is 2 (meaning that the initial value was 0, not 1) -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <datamodel>
+ <data id="Var1" expr="0"/>
+ <!-- contains the previous value -->
+ <data id="Var2"/>
+ <!-- the item which will contain the current value -->
+ <data id="Var3"/>
+ <!-- the index -->
+ <data id="Var4" expr="[1,2,3]"/>
+ <data id="Var5" expr="1"/>
+ <!-- 1 if success, 0 if failure -->
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <foreach item="Var2" array="Var4" index="Var3">
+ <if cond="Var1&lt;Var2">
+ <assign location="Var1" expr="Var2"/>
+ <else/>
+ <!-- values are out of order, record failure -->
+ <assign location="Var5" expr="0"/>
+ </if>
+ </foreach>
+ </onentry>
+ <!-- check that var1 has its original value -->
+ <transition cond="Var4==0 | Var3 != 2" target="fail"/>
+ <transition target="pass"/>
+ </state>
+ <final id="pass">
+ <onentry>
+ <log label="Outcome" expr="'pass'"/>
+ </onentry>
+ </final>
+ <final id="fail">
+ <onentry>
+ <log label="Outcome" expr="'fail'"/>
+ </onentry>
+ </final>
+</scxml>
diff --git a/test/w3c/lua/test460.scxml b/test/w3c/lua/test460.scxml
new file mode 100644
index 0000000..9997296
--- /dev/null
+++ b/test/w3c/lua/test460.scxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- test that <foreach> does a shallow copy, so that modifying the array does not change
+the iteration behavior. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" datamodel="ecmascript" version="1.0">
+ <datamodel>
+ <data id="Var1" expr="[1,2,3]"/>
+ <data id="Var2" expr="0"/>
+ <!-- counts the number of iterations -->
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <foreach item="Var3" array="Var1">
+ <assign location="Var1" expr="[].concat(Var1, [4])"/>
+ <assign location="Var2" expr="Var2 + 1"/>
+ </foreach>
+ </onentry>
+ <transition cond="Var2==3" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass">
+ <onentry>
+ <log label="Outcome" expr="'pass'"/>
+ </onentry>
+ </final>
+ <final id="fail">
+ <onentry>
+ <log label="Outcome" expr="'fail'"/>
+ </onentry>
+ </final>
+</scxml>
diff --git a/test/w3c/lua/test463.scxml b/test/w3c/lua/test463.scxml
new file mode 100644
index 0000000..23ca9cf
--- /dev/null
+++ b/test/w3c/lua/test463.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the <data> tag creates an element in the XML datamodel with the correct name and id attr
+and binds an XPath variable to it -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="foo" expr="2"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="local-name($foo)='data'and $foo/@id ='foo'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test464.scxml b/test/w3c/lua/test464.scxml
new file mode 100644
index 0000000..ddbef86
--- /dev/null
+++ b/test/w3c/lua/test464.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that an unassigned variable creates an empty <data> element -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="foo"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="count($foo) = 1 and count($foo/*) = 0" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test465.scxml b/test/w3c/lua/test465.scxml
new file mode 100644
index 0000000..50e708a
--- /dev/null
+++ b/test/w3c/lua/test465.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that all xpath variables are in a single global scope-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="foo" expr="2"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="count($foo) = 1 and count($bar) = 1" target="s1"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <datamodel>
+ <data id="bar" expr="1"/>
+ </datamodel>
+ <transition target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test466.scxml b/test/w3c/lua/test466.scxml
new file mode 100644
index 0000000..51896b4
--- /dev/null
+++ b/test/w3c/lua/test466.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that xpath expressions are converted to boolean when used as conditional expressions-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="foo" expr="2"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="$foo" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test467.scxml b/test/w3c/lua/test467.scxml
new file mode 100644
index 0000000..673a561
--- /dev/null
+++ b/test/w3c/lua/test467.scxml
@@ -0,0 +1,10 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that in() is available -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <state id="s0">
+ <transition cond="In('s0')" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test468.scxml b/test/w3c/lua/test468.scxml
new file mode 100644
index 0000000..8c0c74a
--- /dev/null
+++ b/test/w3c/lua/test468.scxml
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that XPath expressions can be used as location expressions.
+ This example is taken from the spec -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cities">
+ <list>
+ <city id="nyc" count="0">New York</city>
+ <city id="bos" count="0">Boston</city>
+ </list>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cities/list/city[@id='nyc']/@count" expr="1"/>
+ </onentry>
+ <transition cond="$cities/list/city[@id='nyc']/@count = 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test469.scxml b/test/w3c/lua/test469.scxml
new file mode 100644
index 0000000..487029d
--- /dev/null
+++ b/test/w3c/lua/test469.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that XPath expressions can be used as value expressions. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="copyOfEventData"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="event1">
+ <param name="param1" expr="1"/>
+ </send>
+ </onentry>
+ <transition event="event1" target="s1">
+ <assign location="$copyOfEventData" expr="$_event/data"/>
+ </transition>
+ </state>
+ <state id="s1">
+ <transition cond="$copyOfEventData/data/data[@id='param1'] =1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test470.scxml b/test/w3c/lua/test470.scxml
new file mode 100644
index 0000000..68d55bc
--- /dev/null
+++ b/test/w3c/lua/test470.scxml
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the processor makes a deep copy of a node set when assigning. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="var1">
+ <foo>
+ <bar>2</bar>
+ </foo>
+ </data>
+ <data id="var2"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$var2" expr="$var1/foo"/>
+ <assign location="$var1/foo/bar" expr="3"/>
+ </onentry>
+ <transition cond="$var2/foo/bar=2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test473.scxml b/test/w3c/lua/test473.scxml
new file mode 100644
index 0000000..45dfb40
--- /dev/null
+++ b/test/w3c/lua/test473.scxml
@@ -0,0 +1,36 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that 'replacechildren' in <assign> replaces all children with the new value.
+ This example is taken from the doc -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/books/book[1]">
+ <bookinfo>
+ <isdn>12334455</isdn>
+ <author>some author</author>
+ </bookinfo>
+ </assign>
+ </onentry>
+ <transition cond="$cart/myCart/books/book[1]/bookinfo/isdn/text() = '12334455' and not($cart/myCart/books/book[1]/title)" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test474.scxml b/test/w3c/lua/test474.scxml
new file mode 100644
index 0000000..fdbce30
--- /dev/null
+++ b/test/w3c/lua/test474.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that 'firstchild' in <assign> inserts the new value before the other children. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/books/book[1]" type="firstchild">
+ <bookinfo>
+ <isdn>12334455</isdn>
+ <author>some author</author>
+ </bookinfo>
+ </assign>
+ </onentry>
+ <transition cond="$cart/myCart/books/book[1]/*[1]/isdn/text() = '12334455' and $cart/myCart/books/book[1]/*[2]/text() = 'The Zen Mind'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test475.scxml b/test/w3c/lua/test475.scxml
new file mode 100644
index 0000000..dc01a91
--- /dev/null
+++ b/test/w3c/lua/test475.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that 'lastchild' in <assign> inserts the new value after the other children. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/books/book[1]" type="lastchild">
+ <bookinfo>
+ <isdn>12334455</isdn>
+ <author>some author</author>
+ </bookinfo>
+ </assign>
+ </onentry>
+ <transition cond="$cart/myCart/books/book[1]/*[2]/isdn/text() = '12334455' and $cart/myCart/books/book[1]/*[1]/text() = 'The Zen Mind'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test476.scxml b/test/w3c/lua/test476.scxml
new file mode 100644
index 0000000..fcb7bd9
--- /dev/null
+++ b/test/w3c/lua/test476.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that 'nextsibling' in <assign> inserts the new value after the location. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/books/book[1]/title" type="nextsibling">
+ <bookinfo>
+ <isdn>12334455</isdn>
+ <author>some author</author>
+ </bookinfo>
+ </assign>
+ </onentry>
+ <transition cond="$cart/myCart/books/book[1]/*[2]/isdn/text() = '12334455' and $cart/myCart/books/book[1]/*[1]/text() = 'The Zen Mind'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test477.scxml b/test/w3c/lua/test477.scxml
new file mode 100644
index 0000000..b9ebba9
--- /dev/null
+++ b/test/w3c/lua/test477.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that 'previoussibling' in <assign> inserts the new value before the location. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/books/book[1]/title" type="previoussibling">
+ <bookinfo>
+ <isdn>12334455</isdn>
+ <author>some author</author>
+ </bookinfo>
+ </assign>
+ </onentry>
+ <transition cond="$cart/myCart/books/book[1]/*[1]/isdn/text() = '12334455' and $cart/myCart/books/book[1]/*[2]/text() = 'The Zen Mind'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test478.scxml b/test/w3c/lua/test478.scxml
new file mode 100644
index 0000000..d687487
--- /dev/null
+++ b/test/w3c/lua/test478.scxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that 'replace' in <assign> replaces the value at the location. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/books/book[2]" type="replace">
+ <cd>
+ <title>This is not a book</title>
+ </cd>
+ </assign>
+ </onentry>
+ <transition cond="$cart/myCart/books/cd/title = 'This is not a book'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test479.scxml b/test/w3c/lua/test479.scxml
new file mode 100644
index 0000000..a26ae7b
--- /dev/null
+++ b/test/w3c/lua/test479.scxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that 'delete' in <assign> deletes the value at the location. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/cds" type="delete">
+ <cd>
+ <title>This is not a book</title>
+ </cd>
+ </assign>
+ </onentry>
+ <transition cond="not($cart/myCart/cds)" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test480.scxml b/test/w3c/lua/test480.scxml
new file mode 100644
index 0000000..866444f
--- /dev/null
+++ b/test/w3c/lua/test480.scxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that 'addattr' in <assign> adds an attribute to the specified node. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/books/book[1]" type="addattribute" attr="author" expr="'somebody'"/>
+ </onentry>
+ <transition cond="$cart/myCart/books/book[1]/@author = 'somebody'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test481.scxml b/test/w3c/lua/test481.scxml
new file mode 100644
index 0000000..930b60d
--- /dev/null
+++ b/test/w3c/lua/test481.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that illegal assignments fail and have no side effects. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ <assign location="$cart/myCart/cds/cd/@name">
+ <foo>
+ <bar/>
+ </foo>
+ </assign>
+ </onentry>
+ <transition event="error.execution" cond="$cart/myCart/cds/cd/@name = 'Something'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test482.scxml b/test/w3c/lua/test482.scxml
new file mode 100644
index 0000000..33b35a6
--- /dev/null
+++ b/test/w3c/lua/test482.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that system vars are created and bound to XPath variables -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" name="scxmltest" initial="s0" version="1.0" datamodel="xpath">
+ <state id="s0">
+ <onentry>
+ <!-- event isn't bound until an event is raised -->
+ <raise event="someevent"/>
+ </onentry>
+ <transition event="*" cond="local-name($_event) = 'data' and local-name($_sessionid) = 'data' and local-name($_name) = 'data' and local-name($_ioprocessors) = 'data'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test483.scxml b/test/w3c/lua/test483.scxml
new file mode 100644
index 0000000..375ca05
--- /dev/null
+++ b/test/w3c/lua/test483.scxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that foreach works correctly, iterating over node set in document order.
+ This tests assertions 483-485 -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" name="scxmltest" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="var1">
+ <nodes>
+ <node/>
+ <node/>
+ <node/>
+ </nodes>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <foreach array="$var1/nodes/node" item="item" index="pos">
+ <assign location="$item" type="addattribute" attr="position" expr="$pos"/>
+ </foreach>
+ </onentry>
+ <transition cond="$var1/nodes/node[1]/@position = 1 and $var1/nodes/node[2]/@position = 2 and $var1/nodes/node[3]/@position = 3" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test487.scxml b/test/w3c/lua/test487.scxml
new file mode 100644
index 0000000..95640c3
--- /dev/null
+++ b/test/w3c/lua/test487.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test illegal assignment. error.execution should be raised. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="!" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <raise event="event"/>
+ </onentry>
+ <transition event="error.execution" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test488.scxml b/test/w3c/lua/test488.scxml
new file mode 100644
index 0000000..69d0482
--- /dev/null
+++ b/test/w3c/lua/test488.scxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that illegal expr in <param> produces error.execution and empty event.data -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <!-- we should get the error before the done event -->
+ <transition event="error.execution" target="s1"/>
+ <transition event="done.state.s0" target="fail"/>
+ <transition event="done.state.s0" target="fail">
+ </transition>
+ <state id="s01">
+ <transition target="s02"/>
+ </state>
+ <final id="s02">
+ <donedata>
+ <param name="someParam" expr="!"/>
+ </donedata>
+ </final>
+ </state>
+ <!-- if we get here, we received the error event. Now check that the done
+ event has empty event.data -->
+ <state id="s1">
+ <transition event="done.state.s0" cond="_event.data == nil" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test495.scxml b/test/w3c/lua/test495.scxml
new file mode 100644
index 0000000..bf317e5
--- /dev/null
+++ b/test/w3c/lua/test495.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the scxml event i/o processor puts events in the correct queues.-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <!-- default target is external queue -->
+ <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/>
+ <send event="event2" target="#_internal" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/>
+ </onentry>
+ <!-- we should get the internal event first -->
+ <transition event="event1" target="fail"/>
+ <transition event="event2" target="s1"/>
+ </state>
+ <state id="s1">
+ <transition event="event1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test496.scxml b/test/w3c/lua/test496.scxml
new file mode 100644
index 0000000..ab5a2c0
--- /dev/null
+++ b/test/w3c/lua/test496.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event" target="FIXME"/>
+ <raise event="foo"/>
+ </onentry>
+ <transition event="error.communication" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test500.scxml b/test/w3c/lua/test500.scxml
new file mode 100644
index 0000000..527d36d
--- /dev/null
+++ b/test/w3c/lua/test500.scxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that location field is found inside entry for SCXML Event I/O processor -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="FIXME" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="testvar1 ~= nil" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test501.scxml b/test/w3c/lua/test501.scxml
new file mode 100644
index 0000000..d54f700
--- /dev/null
+++ b/test/w3c/lua/test501.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the location entry for the SCXML Event I/O processor can be used as the target for an event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="FIXME" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="foo" targetexpr="testvar1"/>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <transition event="foo" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test503.scxml b/test/w3c/lua/test503.scxml
new file mode 100644
index 0000000..1926776
--- /dev/null
+++ b/test/w3c/lua/test503.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that a targetless transition does not exit and reenter its source state -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s1" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <!-- how often we have exited s2 -->
+ <data expr="0" id="testvar2"/>
+ <!-- how often the targetless transition in s2 has been executed -->
+ </datamodel>
+ <state id="s1">
+ <onentry>
+ <raise event="foo"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition target="s2"/>
+ </state>
+ <state id="s2">
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ <transition event="foo">
+ <assign location="testvar2" expr="testvar2+1"/>
+ </transition>
+ <!-- make sure the transition on foo was actually taken -->
+ <transition event="bar" target="s3" cond="testvar2 == 1"/>
+ <transition event="bar" target="fail"/>
+ </state>
+ <state id="s3">
+ <!-- make sure that s2 was exited only once -->
+ <transition cond="testvar1 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test504.scxml b/test/w3c/lua/test504.scxml
new file mode 100644
index 0000000..5b0011d
--- /dev/null
+++ b/test/w3c/lua/test504.scxml
@@ -0,0 +1,71 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that an external transition exits all states up the the LCCA -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s1" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <!-- how often we have exited p -->
+ <data expr="0" id="testvar2"/>
+ <!-- how often we have exited ps1 -->
+ <data expr="0" id="testvar3"/>
+ <!-- how often we have exited ps2 -->
+ <data expr="0" id="testvar4"/>
+ <!-- how often the transition for foo has been taken -->
+ <data expr="0" id="testvar5"/>
+ <!-- how often we have exited s2 -->
+ </datamodel>
+ <state id="s1">
+ <onentry>
+ <raise event="foo"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition target="p"/>
+ </state>
+ <state id="s2">
+ <onexit>
+ <assign location="testvar5" expr="testvar5+1"/>
+ </onexit>
+ <parallel id="p">
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ <transition event="foo" target="ps1">
+ <assign location="testvar4" expr="testvar4+1"/>
+ </transition>
+ <!-- make sure the transition on foo was actually taken -->
+ <transition event="bar" target="s3" cond="testvar4 == 1"/>
+ <transition event="bar" target="fail"/>
+ <state id="ps1">
+ <onexit>
+ <assign location="testvar2" expr="testvar2+1"/>
+ </onexit>
+ </state>
+ <state id="ps2">
+ <onexit>
+ <assign location="testvar3" expr="testvar3+1"/>
+ </onexit>
+ </state>
+ </parallel>
+ </state>
+ <state id="s3">
+ <!-- make sure that p was exited twice -->
+ <transition target="s4" cond="testvar1 == 2"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s4">
+ <!-- make sure that ps1 was exited twice -->
+ <transition target="s5" cond="testvar2 == 2"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s5">
+ <!-- make sure that ps2 was exited twice -->
+ <transition target="s6" cond="testvar3 == 2"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s6">
+ <!-- make sure that s1 was exited once -->
+ <transition cond="testvar5 == 1" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test505.scxml b/test/w3c/lua/test505.scxml
new file mode 100644
index 0000000..86da620
--- /dev/null
+++ b/test/w3c/lua/test505.scxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that an internal transition does not exit its source state -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s1" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <!-- how often we have exited s1 -->
+ <data expr="0" id="testvar2"/>
+ <!-- how often we have exited s11 -->
+ <data expr="0" id="testvar3"/>
+ <!-- how often the transition for foo has been taken -->
+ </datamodel>
+ <state id="s1">
+ <onentry>
+ <raise event="foo"/>
+ <raise event="bar"/>
+ </onentry>
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ <transition event="foo" type="internal" target="s11">
+ <assign location="testvar3" expr="testvar3+1"/>
+ </transition>
+ <!-- make sure the transition on foo was actually taken -->
+ <transition event="bar" target="s2" cond="testvar3 == 1"/>
+ <transition event="bar" target="fail"/>
+ <state id="s11">
+ <onexit>
+ <assign location="testvar2" expr="testvar2+1"/>
+ </onexit>
+ </state>
+ </state>
+ <state id="s2">
+ <!-- make sure that s1 was exited once -->
+ <transition target="s3" cond="testvar1 == 1"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s3">
+ <!-- make sure that s11 was exited twice -->
+ <transition cond="testvar2 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test506.scxml b/test/w3c/lua/test506.scxml
new file mode 100644
index 0000000..0548023
--- /dev/null
+++ b/test/w3c/lua/test506.scxml
@@ -0,0 +1,48 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that an internal transition whose targets are not proper descendants of its source state
+behaves like an external transition -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s1" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <!-- how often we have exited s2 -->
+ <data expr="0" id="testvar2"/>
+ <!-- how often we have exited s21 -->
+ <data expr="0" id="testvar3"/>
+ <!-- how often the transition for foo has been taken -->
+ </datamodel>
+ <state id="s1">
+ <onentry>
+ <raise event="foo"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition target="s2"/>
+ </state>
+ <state id="s2" initial="s21">
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ <transition event="foo" type="internal" target="s2">
+ <assign location="testvar3" expr="testvar3+1"/>
+ </transition>
+ <!-- make sure the transition on foo was actually taken -->
+ <transition event="bar" target="s3" cond="testvar3 == 1"/>
+ <transition event="bar" target="fail"/>
+ <state id="s21">
+ <onexit>
+ <assign location="testvar2" expr="testvar2+1"/>
+ </onexit>
+ </state>
+ </state>
+ <state id="s3">
+ <!-- make sure that s2 was exited twice -->
+ <transition target="s4" cond="testvar1 == 2"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s4">
+ <!-- make sure that s21 was exited twice -->
+ <transition cond="testvar2 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test509.scxml b/test/w3c/lua/test509.scxml
new file mode 100644
index 0000000..8dd27c5
--- /dev/null
+++ b/test/w3c/lua/test509.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that Basic HTTP Event I/O processor uses POST method and that it can receive messages
+at the accessURI -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME"/>
+ </onentry>
+ <!-- if the event was send by http and we get it, we succeed -->
+ <transition event="test" cond="_event.httpmethod=='POST'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test510.scxml b/test/w3c/lua/test510.scxml
new file mode 100644
index 0000000..2ccd802
--- /dev/null
+++ b/test/w3c/lua/test510.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that Basic HTTP messages go into external queue. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME"/>
+ <!-- this creates an internal event -->
+ <raise event="internal"/>
+ </onentry>
+ <!-- we should get 'internal' first, then 'test' -->
+ <transition event="internal" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition event="test" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test513.txt b/test/w3c/lua/test513.txt
new file mode 100644
index 0000000..08e9b01
--- /dev/null
+++ b/test/w3c/lua/test513.txt
@@ -0,0 +1,16 @@
+This is a fully manual test. You send a well formed event to the 'location' URL
+ specified for your SCXML interpreter and check that you get a 200 response code back.
+ One way of doing this, using wget, is shown below (you can use any event name you
+ want, but you must use '_scxmleventname' to indicate the name of the event):
+
+$ wget \
+--post-data='key1=value1&key2=value2' \
+--header '_scxmleventname: test' \
+<!-- URL of your processor goes here -->
+
+--2014-06-25 17:54:49-- http://epikur.local:8090/925c760f-2093-4054-a24c-d972d75f0dcd/basichttp
+Resolving epikur.local (epikur.local)... 10.211.55.2, 10.37.129.2, 10.0.1.54, ...
+Connecting to epikur.local (epikur.local)|10.211.55.2|:8090... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 0 [text/html]
+Saving to: ‘basichttp’ \ No newline at end of file
diff --git a/test/w3c/lua/test518.scxml b/test/w3c/lua/test518.scxml
new file mode 100644
index 0000000..35b0db6
--- /dev/null
+++ b/test/w3c/lua/test518.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that that namelist values get encoded as POST parameters. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="2" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" namelist="testvar1" targetexpr="FIXME"/>
+ </onentry>
+ <transition event="test" cond="_event.data.testvar1==2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test519.scxml b/test/w3c/lua/test519.scxml
new file mode 100644
index 0000000..0287f8a
--- /dev/null
+++ b/test/w3c/lua/test519.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that that <param> values get encoded as POST parameters. . -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME">
+ <param name="param1" expr="1"/>
+ </send>
+ </onentry>
+ <!-- if other end sends us back this event, we succeed -->
+ <transition event="test" cond="_event.data.param1==1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test520.scxml b/test/w3c/lua/test520.scxml
new file mode 100644
index 0000000..2e2e356
--- /dev/null
+++ b/test/w3c/lua/test520.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that that <content> gets sent as the body of the message. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ <send type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME">
+ <content>this is some content</content>
+ </send>
+ </onentry>
+ <!-- if other end sends us back this event, we succeed. Test for two common
+ ways of encoding -->
+ <transition event="HTTP.POST" cond="_event.httpresponse=='this+is+some+content'" target="pass"/>
+ <transition event="HTTP.POST" cond="_event.httpresponse=='this%20is%20some%20content'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test521.scxml b/test/w3c/lua/test521.scxml
new file mode 100644
index 0000000..5c79990
--- /dev/null
+++ b/test/w3c/lua/test521.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that the processor raises error.communication if it cannot dispatch the event.
+(To create an undispatchable event, we choose a non-existent session as target). If it raises
+the error event, we succeed. Otherwise we eventually timeout and fail. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <!-- should cause an error -->
+ <send event="event2" target="FIXME"/>
+ <!-- this will get added to the external event queue after the error has been raised -->
+ <send event="timeout"/>
+ </onentry>
+ <!-- once we've entered the state, we should check for internal events first -->
+ <transition event="error.communication" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test522.scxml b/test/w3c/lua/test522.scxml
new file mode 100644
index 0000000..18db5f0
--- /dev/null
+++ b/test/w3c/lua/test522.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that location field the entry for Basic HTTP Event I/O processor can be used
+to send a message to the processor -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME"/>
+ </onentry>
+ <!-- the event we receive should be called 'test', but that's not actually
+ required for this test. Only that the send deliver some event to us. So if
+ we get something other than timeout or error, we call it success -->
+ <transition event="timeout" target="fail"/>
+ <transition event="error" target="fail"/>
+ <transition event="*" target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test525.scxml b/test/w3c/lua/test525.scxml
new file mode 100644
index 0000000..5831767
--- /dev/null
+++ b/test/w3c/lua/test525.scxml
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that <foreach> does a shallow copy, so that modifying the array does not change
+the iteration behavior. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="lua">
+ <datamodel>
+ <data id="testvar1">{1,2,3}</data>
+ <data expr="0" id="testvar2"/>
+ <!-- counts the number of iterations -->
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <foreach array="testvar1" item="testvar3">
+ <assign location="testvar1" expr="(function() local t2={}; for i=1,#testvar1 do t2[i]=testvar1[i] end t2[#t2+1]=4 return t2 end)()"/>
+ <assign location="testvar2" expr="testvar2+1"/>
+ </foreach>
+ </onentry>
+ <transition cond="testvar2 == 3" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test527.scxml b/test/w3c/lua/test527.scxml
new file mode 100644
index 0000000..79d17c5
--- /dev/null
+++ b/test/w3c/lua/test527.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- simple test that 'expr' works with <content> -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <transition event="done.state.s0" cond="_event.data == 'foo'" target="pass">
+ </transition>
+ <transition event="done.state.s0" target="fail">
+ </transition>
+ <state id="s01">
+ <transition target="s02"/>
+ </state>
+ <final id="s02">
+ <donedata>
+ <content expr="'foo'"/>
+ </donedata>
+ </final>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test528.scxml b/test/w3c/lua/test528.scxml
new file mode 100644
index 0000000..051cfd8
--- /dev/null
+++ b/test/w3c/lua/test528.scxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that illegal 'expr' produces error.execution and empty event.data -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <!-- we should get the error before the done event -->
+ <transition event="error.execution" target="s1"/>
+ <transition event="done.state.s0" target="fail"/>
+ <state id="s01">
+ <transition target="s02"/>
+ </state>
+ <final id="s02">
+ <donedata>
+ <content expr="!"/>
+ </donedata>
+ </final>
+ </state>
+ <!-- if we get here, we received the error event. Now check that the done
+ event has empty event.data -->
+ <state id="s1">
+ <transition event="done.state.s0" cond="_event.data == nil" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test529.scxml b/test/w3c/lua/test529.scxml
new file mode 100644
index 0000000..ace3214
--- /dev/null
+++ b/test/w3c/lua/test529.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- simple test that children workn with <content> -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0" initial="s01">
+ <transition event="done.state.s0" cond="_event.data == 21" target="pass">
+ </transition>
+ <transition event="done.state.s0" target="fail">
+ </transition>
+ <state id="s01">
+ <transition target="s02"/>
+ </state>
+ <final id="s02">
+ <donedata>
+ <content>21</content>
+ </donedata>
+ </final>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test530.scxml b/test/w3c/lua/test530.scxml
new file mode 100644
index 0000000..28c2047
--- /dev/null
+++ b/test/w3c/lua/test530.scxml
@@ -0,0 +1,26 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that <content> child is evaluated when <invoke> is. Var1 is initialized
+with an integer value, then set to an scxml script in the onentry to s0. If <content>
+is evaluated at the right time, we should get invoke.done, otherwise an error -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="1" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="testvar1">
+ <scxml version="1.0">
+ <final/>
+ </scxml>
+ </assign>
+ <send event="timeout" delay="2s"/>
+ </onentry>
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content expr="testvar1"/>
+ </invoke>
+ <transition event="done.invoke" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test531.scxml b/test/w3c/lua/test531.scxml
new file mode 100644
index 0000000..36d8301
--- /dev/null
+++ b/test/w3c/lua/test531.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that that the value of the <param> _scxmleventname gets used as the name
+of the raised event. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ <send type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME">
+ <param name="_scxmleventname" expr="'test'"/>
+ </send>
+ </onentry>
+ <!-- if we get an event named 'test' we succeed. Otherwise fail -->
+ <transition event="test" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test532.scxml b/test/w3c/lua/test532.scxml
new file mode 100644
index 0000000..e9514a4
--- /dev/null
+++ b/test/w3c/lua/test532.scxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that that if _scxmleventname is not present, the name of the HTTP method is used
+as the name of the resulting event. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ <send type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME">
+ <!-- this content will be ignored, but it's here to make sure we have a message body -->
+ <content>some content</content>
+ </send>
+ </onentry>
+ <transition event="HTTP.POST" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test533.scxml b/test/w3c/lua/test533.scxml
new file mode 100644
index 0000000..6407cfe
--- /dev/null
+++ b/test/w3c/lua/test533.scxml
@@ -0,0 +1,59 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that an internal transition whose source state is not compound does exit its source state -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s1" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ <!-- how often we have exited p -->
+ <data expr="0" id="testvar2"/>
+ <!-- how often we have exited ps1 -->
+ <data expr="0" id="testvar3"/>
+ <!-- how often we have exited ps2 -->
+ <data expr="0" id="testvar4"/>
+ <!-- how often the transition for foo has been taken -->
+ </datamodel>
+ <state id="s1">
+ <onentry>
+ <raise event="foo"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition target="p"/>
+ </state>
+ <parallel id="p">
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ <transition event="foo" type="internal" target="ps1">
+ <assign location="testvar4" expr="testvar4+1"/>
+ </transition>
+ <!-- make sure the transition on foo was actually taken -->
+ <transition event="bar" target="s2" cond="testvar4 == 1"/>
+ <transition event="bar" target="fail"/>
+ <state id="ps1">
+ <onexit>
+ <assign location="testvar2" expr="testvar2+1"/>
+ </onexit>
+ </state>
+ <state id="ps2">
+ <onexit>
+ <assign location="testvar3" expr="testvar3+1"/>
+ </onexit>
+ </state>
+ </parallel>
+ <state id="s2">
+ <!-- make sure that p was exited twice -->
+ <transition target="s3" cond="testvar1 == 2"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s3">
+ <!-- make sure that ps1 was exited twice -->
+ <transition target="s4" cond="testvar2 == 2"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s4">
+ <!-- make sure that ps2 was exited twice -->
+ <transition cond="testvar3 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test534.scxml b/test/w3c/lua/test534.scxml
new file mode 100644
index 0000000..c206bc0
--- /dev/null
+++ b/test/w3c/lua/test534.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that that <send> 'event' value gets sent as the param _scxmleventname . -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="30s"/>
+ <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME">
+ </send>
+ </onentry>
+ <!-- if other end sends us back this event, we succeed -->
+ <transition event="test" cond="_event.data._scxmleventname==test" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test537.scxml b/test/w3c/lua/test537.scxml
new file mode 100644
index 0000000..a231a97
--- /dev/null
+++ b/test/w3c/lua/test537.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the root element of the datamodel is <datamodel> and that <data> elements are its
+children-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="foo" expr="2"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="local-name($foo/..)='datamodel'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test539.scxml b/test/w3c/lua/test539.scxml
new file mode 100644
index 0000000..fced2e6
--- /dev/null
+++ b/test/w3c/lua/test539.scxml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that if the child of <data> is XML, or if XML is loaded via src=, the processor
+ assigns it as the value of the var -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="var1">
+ <books>
+ <book title="title1"/>
+ <book title="title2"/>
+ </books>
+ </data>
+ <data id="var2" src="file:test539.txt"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="$var1/books/book[2]/@title = 'title2'" target="s1"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="$var2/books/book[2]/@title = 'title2'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test539.txt b/test/w3c/lua/test539.txt
new file mode 100644
index 0000000..de1b0a1
--- /dev/null
+++ b/test/w3c/lua/test539.txt
@@ -0,0 +1,4 @@
+ <books xmlns="">
+ <book title="title1"/>
+ <book title="title2"/>
+ </books> \ No newline at end of file
diff --git a/test/w3c/lua/test540.scxml b/test/w3c/lua/test540.scxml
new file mode 100644
index 0000000..b0298b7
--- /dev/null
+++ b/test/w3c/lua/test540.scxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that if the child of <data> is a string or if a string is loaded via src=, the processor
+ does white space normalization on it and assigns it as the value of the var -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="var1">123
+4 5
+</data>
+ <data id="var2" src="file:test540.txt"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <log label="var1 " expr="$var1"/>
+ </onentry>
+ <transition cond="$var1 = '123 4 5' and $var2 = '123 4 5'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test540.txt b/test/w3c/lua/test540.txt
new file mode 100644
index 0000000..2191239
--- /dev/null
+++ b/test/w3c/lua/test540.txt
@@ -0,0 +1,3 @@
+123
+4 5
+ \ No newline at end of file
diff --git a/test/w3c/lua/test542.scxml b/test/w3c/lua/test542.scxml
new file mode 100644
index 0000000..69b6ea3
--- /dev/null
+++ b/test/w3c/lua/test542.scxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that <content> inside <donedata> handles XML and strings,
+ including white space normalization. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <state id="s0" initial="s01">
+ <transition event="done.state.s0" cond="$_event/data/books/book[1]/@title = 'title1'" target="s1"/>
+ <transition event="done" target="fail"/>
+ <final id="s01">
+ <donedata>
+ <content>
+ <books>
+ <book title="title1"/>
+ <book title="title2"/>
+ </books>
+ </content>
+ </donedata>
+ </final>
+ </state>
+ <state id="s1" initial="s11">
+ <transition event="done.state.s1" cond="$_event/data = '123 4 5'" target="pass"/>
+ <transition event="done" target="fail"/>
+ <final id="s11">
+ <donedata>
+ <content>123
+4 5
+ </content>
+ </donedata>
+ </final>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test543.scxml b/test/w3c/lua/test543.scxml
new file mode 100644
index 0000000..55946ed
--- /dev/null
+++ b/test/w3c/lua/test543.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that event fields are present as children of _event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" name="scxmltest" initial="s0" version="1.0" datamodel="xpath">
+ <state id="s0">
+ <onentry>
+ <!-- event isn't bound until an event is raised -->
+ <raise event="someevent"/>
+ </onentry>
+ <!-- origintype sendid, invokeid and data will not be bound in this event. name, type, and origin
+ are guaranteed to be there. -->
+ <transition event="*" cond="$_event/name and $_event/origin and $_event/type" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test544.scxml b/test/w3c/lua/test544.scxml
new file mode 100644
index 0000000..5d935ab
--- /dev/null
+++ b/test/w3c/lua/test544.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that kvps are represented as <data> elements under event/data -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" name="scxmltest" initial="s0" version="1.0" datamodel="xpath">
+ <state id="s0">
+ <onentry>
+ <send event="someevent">
+ <param name="key1" expr="2"/>
+ </send>
+ </onentry>
+ <transition event="*" cond="$_event/data/data[@id='key1'] = 2" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test545.scxml b/test/w3c/lua/test545.scxml
new file mode 100644
index 0000000..7443ff2
--- /dev/null
+++ b/test/w3c/lua/test545.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that xml content in send is place as XML under event/data -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" name="scxmltest" initial="s0" version="1.0" datamodel="xpath">
+ <state id="s0">
+ <onentry>
+ <send event="someevent">
+ <content>
+ <foo>
+ <bar>3</bar>
+ </foo>
+ </content>
+ </send>
+ </onentry>
+ <transition event="*" cond="$_event/data/foo/bar = 3" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test546.scxml b/test/w3c/lua/test546.scxml
new file mode 100644
index 0000000..68efb84
--- /dev/null
+++ b/test/w3c/lua/test546.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that string content in send is place as a string under event/data -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" name="scxmltest" initial="s0" version="1.0" datamodel="xpath">
+ <state id="s0">
+ <onentry>
+ <send event="someevent">
+ <content>some string</content>
+ </send>
+ </onentry>
+ <transition event="*" cond="$_event/data = 'some string'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test547.scxml b/test/w3c/lua/test547.scxml
new file mode 100644
index 0000000..26e5cc8
--- /dev/null
+++ b/test/w3c/lua/test547.scxml
@@ -0,0 +1,31 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that assiging to a node set performs the assignment to each node.
+ This example is taken from the spec. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" name="scxmltest" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="cart">
+ <myCart>
+ <books>
+ <book>
+ <title>The Zen Mind</title>
+ </book>
+ <book>
+ <title>Freakonomics</title>
+ </book>
+ </books>
+ <cds>
+ <cd name="Something"/>
+ </cds>
+ </myCart>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <assign location="$cart/myCart/books/book" expr="'The Zen Mind'"/>
+ </onentry>
+ <transition cond="$cart/myCart/books/book[1] = 'The Zen Mind' and $cart/myCart/books/book[2] = 'The Zen Mind'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test550.scxml b/test/w3c/lua/test550.scxml
new file mode 100644
index 0000000..93d514c
--- /dev/null
+++ b/test/w3c/lua/test550.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that expr can be used to assign a value to a var. This test uses early binding -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" binding="early" datamodel="lua">
+ <state id="s0">
+ <transition cond="testvar1 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <datamodel>
+ <data expr="2" id="testvar1"/>
+ </datamodel>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test551.scxml b/test/w3c/lua/test551.scxml
new file mode 100644
index 0000000..6836896
--- /dev/null
+++ b/test/w3c/lua/test551.scxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that inline content can be used to assign a value to a var. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" binding="early" datamodel="lua">
+ <state id="s0">
+ <transition cond="testvar1 ~= nil" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <datamodel>
+ <data id="testvar1">{1,2,3}</data>
+ </datamodel>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test552.scxml b/test/w3c/lua/test552.scxml
new file mode 100644
index 0000000..154d60e
--- /dev/null
+++ b/test/w3c/lua/test552.scxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that src content can be used to assign a value to a var. Edit
+test552.txt to have a value that's legal for the datamodel in question -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data src="file:test552.txt" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="testvar1 ~= nil" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test552.txt b/test/w3c/lua/test552.txt
new file mode 100644
index 0000000..d8263ee
--- /dev/null
+++ b/test/w3c/lua/test552.txt
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/w3c/lua/test553.scxml b/test/w3c/lua/test553.scxml
new file mode 100644
index 0000000..cf926e7
--- /dev/null
+++ b/test/w3c/lua/test553.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- we test that the processor does not dispatch the event if evaluation
+of <send>'s args causes an error.. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <!-- timeout event -->
+ <send event="timeout" delay="100ms"/>
+ <!-- generate an invalid namelist -->
+ <send event="event1" namelist=""/>
+ </onentry>
+ <!-- if we get the timeout before event1, we assume that event1 hasn't been sent
+ We ignore the error event here because this assertion doesn't mention it -->
+ <transition event="timeout" target="pass"/>
+ <transition event="event1" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test554.scxml b/test/w3c/lua/test554.scxml
new file mode 100644
index 0000000..5c46992
--- /dev/null
+++ b/test/w3c/lua/test554.scxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that if the evaluation of <invoke>'s args causes an error, the
+invocation is cancelled. In this test, that means that we don't get done.invoke
+before the timer goes off. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <send event="timer" delay="100ms"/>
+ </onentry>
+ <!-- reference an invalid namelist -->
+ <invoke type="http://www.w3.org/TR/scxml/" namelist="">
+ <content>
+ <scxml initial="subFinal" version="1.0" datamodel="lua">
+ <final id="subFinal"/>
+ </scxml>
+ </content>
+ </invoke>
+ <transition event="timer" target="pass"/>
+ <transition event="done.invoke" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test555.scxml b/test/w3c/lua/test555.scxml
new file mode 100644
index 0000000..2609689
--- /dev/null
+++ b/test/w3c/lua/test555.scxml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!-- in the XPATH data model, test that processor coerces types to produce a string
+ where it's needed -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <datamodel>
+ <data id="var1">
+ <books>
+ <book title="title1"/>
+ <book title="title2"/>
+ </books>
+ </data>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send eventexpr="$var1"/>
+ </onentry>
+ <transition event="error" target="fail"/>
+ <!-- don't really know what the stringification of that xml structure should be, but if
+ we get something other than an error, we assume that it worked. -->
+ <transition event="*" target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test557.scxml b/test/w3c/lua/test557.scxml
new file mode 100644
index 0000000..bec74d0
--- /dev/null
+++ b/test/w3c/lua/test557.scxml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!-- in the ECMA data model, test that if the child of <data> is XML, or if XML is loaded via src=, the processor
+ assigns it as the value of the var -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <datamodel>
+ <data id="var1">
+ <books>
+ <book title="title1"/>
+ <book title="title2"/>
+ </books>
+ </data>
+ <data id="var2" src="file:test557.txt"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="var1.getElementsByTagName('book')[0].getAttribute('title') == 'title1'" target="s1"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="var2.getElementsByTagName('book')[1].getAttribute('title') == 'title2'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test557.txt b/test/w3c/lua/test557.txt
new file mode 100644
index 0000000..a8e51da
--- /dev/null
+++ b/test/w3c/lua/test557.txt
@@ -0,0 +1,4 @@
+<books xmlns="">
+ <book title="title1"/>
+ <book title="title2"/>
+ </books> \ No newline at end of file
diff --git a/test/w3c/lua/test558.scxml b/test/w3c/lua/test558.scxml
new file mode 100644
index 0000000..0ff6f90
--- /dev/null
+++ b/test/w3c/lua/test558.scxml
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="no"?>
+<!-- in the ECMA data model, test that if the child of <data> is not XML, or if XML is loaded via src=,
+ the processor treats the value as a string, does whitespace normalization and assigns it to the var.-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <datamodel>
+ <data id="var1">
+this is
+a string
+</data>
+ <data id="var2" src="file:test558.txt"/>
+ </datamodel>
+ <state id="s0">
+ <transition cond="var1 == 'this is a string'" target="s1"/>
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="var2 == 'this is a string'" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test558.txt b/test/w3c/lua/test558.txt
new file mode 100644
index 0000000..bb2bcc7
--- /dev/null
+++ b/test/w3c/lua/test558.txt
@@ -0,0 +1,3 @@
+
+this is
+a string \ No newline at end of file
diff --git a/test/w3c/lua/test560.scxml b/test/w3c/lua/test560.scxml
new file mode 100644
index 0000000..cb0d563
--- /dev/null
+++ b/test/w3c/lua/test560.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- in the ECMA data model, test that processor creates correct structure in
+ _event.data when receiving KVPs in an event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <state id="s0">
+ <onentry>
+ <send event="foo">
+ <param name="aParam" expr="1"/>
+ </send>
+ </onentry>
+ <transition event="foo" cond="_event.data.aParam == 1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test561.scxml b/test/w3c/lua/test561.scxml
new file mode 100644
index 0000000..77acad4
--- /dev/null
+++ b/test/w3c/lua/test561.scxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" standalone="no"?>
+<!-- in the ECMA data model, test that processor creates an ECMAScript DOM object
+ _event.data when receiving XML in an event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <state id="s0">
+ <onentry>
+ <send event="foo">
+ <content>
+ <books>
+ <book title="title1"/>
+ <book title="title2"/>
+ </books>
+ </content>
+ </send>
+ </onentry>
+ <transition event="foo" cond="_event.data.getElementsByTagName('book')[1].getAttribute('title') == 'title2'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test562.scxml b/test/w3c/lua/test562.scxml
new file mode 100644
index 0000000..99e86e5
--- /dev/null
+++ b/test/w3c/lua/test562.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!-- in the ECMA data model, test that processor creates space normalized string in
+ _event.data when receiving anything other than KVPs or XML in an event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <state id="s0">
+ <onentry>
+ <send event="foo">
+ <content>
+this is a
+string
+</content>
+ </send>
+ </onentry>
+ <transition event="foo" cond="_event.data == 'this is a string'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test567.scxml b/test/w3c/lua/test567.scxml
new file mode 100644
index 0000000..0e9b4ca
--- /dev/null
+++ b/test/w3c/lua/test567.scxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that that any content in the message other than _scxmleventname is used to populate
+_event.data. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="2" id="testvar1"/>
+ </datamodel>
+ <state id="s0">
+ <onentry>
+ <send event="timeout" delay="3s"/>
+ <!-- in this case, 'test' will be placed in _scxmleventname. The <param> should
+ be used to populate _event.data -->
+ <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="FIXME">
+ <param name="param1" expr="2"/>
+ </send>
+ </onentry>
+ <!-- if we get this event, we succeed -->
+ <transition event="test" target="s1">
+ <assign expr="_event.data.param1" location="testvar1"/>
+ </transition>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition cond="testvar1 == 2" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test568.scxml b/test/w3c/lua/test568.scxml
new file mode 100644
index 0000000..aaa1023
--- /dev/null
+++ b/test/w3c/lua/test568.scxml
@@ -0,0 +1,12 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that location field is found inside entry for SCXML Event I/O processor in the XPath
+data model. The tests for the relevant event i/o processors will test that it can be used to
+send events. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="xpath">
+ <state id="s0">
+ <transition cond="$_ioprocessors/[@name='http://www.w3.org/TR/scxml/#SCXMLEventProcessor']/location/text()" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test569.scxml b/test/w3c/lua/test569.scxml
new file mode 100644
index 0000000..ec6fe13
--- /dev/null
+++ b/test/w3c/lua/test569.scxml
@@ -0,0 +1,12 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that location field is found inside entry for SCXML Event I/O processor in the ECMAScript
+data model. The tests for the relevant event i/o processors will test that it can be used to
+send events. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <state id="s0">
+ <transition cond="_ioprocessors['scxml'].location" target="pass"/>
+ <transition target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test570.scxml b/test/w3c/lua/test570.scxml
new file mode 100644
index 0000000..659789e
--- /dev/null
+++ b/test/w3c/lua/test570.scxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that we generate done.state.id when all a parallel state's children are in final states -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="p0" version="1.0" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <parallel id="p0">
+ <onentry>
+ <send event="timeout" delay="2s"/>
+ <raise event="e1"/>
+ <raise event="e2"/>
+ </onentry>
+ <!-- record that we get the first done event -->
+ <transition event="done.state.p0s1">
+ <assign expr="1" location="testvar1"/>
+ </transition>
+ <!-- we should get the second done event before done.state.p0 -->
+ <transition event="done.state.p0s2" target="s1"/>
+ <transition event="timeout" target="fail"/>
+ <state id="p0s1" initial="p0s11">
+ <state id="p0s11">
+ <transition event="e1" target="p0s1final"/>
+ </state>
+ <final id="p0s1final"/>
+ </state>
+ <state id="p0s2" initial="p0s21">
+ <state id="p0s21">
+ <transition event="e2" target="p0s2final"/>
+ </state>
+ <final id="p0s2final"/>
+ </state>
+ </parallel>
+ <state id="s1">
+ <!-- if we get done.state.p0, success -->
+ <transition event="done.state.p0" cond="testvar1 == 1" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test576.scxml b/test/w3c/lua/test576.scxml
new file mode 100644
index 0000000..195f3e4
--- /dev/null
+++ b/test/w3c/lua/test576.scxml
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that the 'initial' value of scxml is respected. We set the value to deeply nested non-default parallel siblings and
+test that both are entered. -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s11p112 s11p122" version="1.0" datamodel="lua">
+ <state id="s0">
+ <transition target="fail"/>
+ </state>
+ <state id="s1">
+ <onentry>
+ <send event="timeout" delay="1s"/>
+ </onentry>
+ <transition event="timeout" target="fail"/>
+ <state id="s11" initial="s111">
+ <state id="s111"/>
+ <parallel id="s11p1">
+ <state id="s11p11" initial="s11p111">
+ <state id="s11p111"/>
+ <state id="s11p112">
+ <onentry>
+ <raise event="In-s11p112"/>
+ </onentry>
+ </state>
+ </state>
+ <state id="s11p12" initial="s11p121">
+ <state id="s11p121"/>
+ <state id="s11p122">
+ <transition event="In-s11p112" target="pass"/>
+ </state>
+ </state>
+ </parallel>
+ </state>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test577.scxml b/test/w3c/lua/test577.scxml
new file mode 100644
index 0000000..a652461
--- /dev/null
+++ b/test/w3c/lua/test577.scxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that that <send> without target in basichttp event i/o processor
+causes error.communication to get added to internal queue . -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="lua">
+ <state id="s0">
+ <onentry>
+ <!-- sent by scxml event i/o processor, added to external queue -->
+ <send event="event1"/>
+ <!-- should put error.communication on internal queue -->
+ <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/>
+ </onentry>
+ <transition event="error.communication" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test578.scxml b/test/w3c/lua/test578.scxml
new file mode 100644
index 0000000..8de6e25
--- /dev/null
+++ b/test/w3c/lua/test578.scxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+<!-- in the ECMA data model, test that processor creates an ECMAScript object
+ _event.data when receiving JSON in an event -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s0" version="1.0" datamodel="ecmascript">
+ <state id="s0">
+ <onentry>
+ <send event="foo">
+ <content>{ "productName" : "bar", "size" : 27 }</content>
+ </send>
+ </onentry>
+ <transition event="foo" cond="_event.data.productName == 'bar'" target="pass"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test579.scxml b/test/w3c/lua/test579.scxml
new file mode 100644
index 0000000..b23ccbf
--- /dev/null
+++ b/test/w3c/lua/test579.scxml
@@ -0,0 +1,52 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that default history content is executed correctly. The Process MUST execute any executable content in the transition after the parent state's onentry handlers, and, in the case where the history pseudo-state is the target of an <initial> transition,
+the executable content inside the <initial> transition. However the Processor MUST
+execute this content only if there is no stored history. Once the history state's
+parent state has been visited and exited, the default history content must not be executed -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0" datamodel="lua">
+ <state id="s0">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <initial>
+ <transition target="sh1">
+ <raise event="event2"/>
+ </transition>
+ </initial>
+ <onentry>
+ <send event="timeout" delay="100ms"/>
+ <raise event="event1"/>
+ </onentry>
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ <history id="sh1">
+ <transition target="s01">
+ <raise event="event3"/>
+ </transition>
+ </history>
+ <state id="s01">
+ <transition event="event1" target="s02"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s02">
+ <transition event="event2" target="s03"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s03">
+ <transition event="event3" target="s0" cond="testvar1 == 0"/>
+ <transition event="event1" target="s2" cond="testvar1 == 1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ </state>
+ <state id="s2">
+ <transition event="event2" target="s3"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s3">
+ <transition event="event3" target="fail"/>
+ <transition event="timeout" target="pass"/>
+ </state>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>
diff --git a/test/w3c/lua/test580.scxml b/test/w3c/lua/test580.scxml
new file mode 100644
index 0000000..da066b3
--- /dev/null
+++ b/test/w3c/lua/test580.scxml
@@ -0,0 +1,37 @@
+<?xml version="1.0" standalone="no"?>
+<!-- test that a history state never ends up part of the configuration -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="p1" datamodel="lua">
+ <datamodel>
+ <data expr="0" id="testvar1"/>
+ </datamodel>
+ <parallel id="p1">
+ <onentry>
+ <send delay="2s" event="timeout"/>
+ </onentry>
+ <state id="s0">
+ <transition cond="In('sh1')" target="fail"/>
+ <transition event="timeout" target="fail"/>
+ </state>
+ <state id="s1">
+ <initial>
+ <transition target="sh1"/>
+ </initial>
+ <history id="sh1">
+ <transition target="s11"/>
+ </history>
+ <state id="s11">
+ <transition cond="In('sh1')" target="fail"/>
+ <transition target="s12"/>
+ </state>
+ <state id="s12"/>
+ <transition cond="In('sh1')" target="fail"/>
+ <transition target="sh1" cond="testvar1 == 0"/>
+ <transition cond="testvar1 == 1" target="pass"/>
+ <onexit>
+ <assign location="testvar1" expr="testvar1+1"/>
+ </onexit>
+ </state>
+ </parallel>
+ <final id="pass"/>
+ <final id="fail"/>
+</scxml>