summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Gossage <mark@gossage.cjb.net>2006-12-21 04:53:12 +0000
committerMark Gossage <mark@gossage.cjb.net>2006-12-21 04:53:12 +0000
commitbc08e0f335abd1d86db71ad89a2d9be46a3a1b32 (patch)
tree184e1e5f9d7a1ede61ea057e47d07d237db0787c
parente284fcbf02881039aee9ce003e1f2647444ccdcf (diff)
downloadswig-bc08e0f335abd1d86db71ad89a2d9be46a3a1b32.tar.gz
making setting immutables an error
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9626 626c5289-ae23-0410-ae9c-e8d60b6d4f22
-rw-r--r--CHANGES.current4
-rw-r--r--Doc/Manual/Lua.html38
-rw-r--r--Examples/lua/variables/runme.lua19
-rw-r--r--Examples/test-suite/lua/li_std_string_runme.lua9
-rw-r--r--Lib/lua/luarun.swg23
-rw-r--r--Source/Modules/lua.cxx36
6 files changed, 90 insertions, 39 deletions
diff --git a/CHANGES.current b/CHANGES.current
index 7cd29d705..3fb9f334a 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -1,6 +1,10 @@
Version 1.3.32 (in progress)
============================
+12/21/2006: mgossage
+ [Lua] Update to throw errors when setting immutables,
+ and allowing user addition of module variables.
+
12/20/2006: wsfulton
Fix typedef'd variable wrappers that use %naturalvar, eg, std::string.
diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html
index d3a9b7647..962d22094 100644
--- a/Doc/Manual/Lua.html
+++ b/Doc/Manual/Lua.html
@@ -311,20 +311,39 @@ Its is therefore not possible to 'move' the global variable into the global name
4
</pre></div>
<p>
-If a variable is marked with the immutable directive then any attempts to set this variable are silently ignored.
+If a variable is marked with the %immutable directive then any attempts to set this variable will cause an lua error. Given a global variable:
</p>
+
+<div class="code"><pre>%module example
+%immutable;
+extern double Foo;
+%mutable;
+</pre></div>
<p>
-Another interesting feature is that it is not possible to add new values into the module from within the interpreter, this is because of the metatable to deal with global variables. It is possible (though not recommended) to use rawset() to add a new value.
+SWIG will generate the <tt>example.Foo_get()</tt> but instead of a set function an error function will be called instead.
+</p>
+<div class="targetlang"><pre>
+&gt; print(e.Foo) -- reading works ok
+4
+&gt; example.Foo=40 -- but writing does not
+This variable is immutable
+stack traceback:
+ [C]: ?
+ [C]: ?
+ stdin:1: in main chunk
+ [C]: ?
+</pre></div>
+<p>
+For those people who would rather that SWIG silently ignore the setting of immutables (as previous versions of the lua bindings did), adding a <tt>-DSWIGLUA_IGNORE_SET_IMMUTABLE</tt> compile option will remove this.
+</p>
+<p>
+Unlike earlier versions of the binding, it is now possible to add new functions or variables to the module, just as if it were a normal table. This does allow the user to rename/remove existing functions and constants (but not linked variables, mutable or immutable). Therefore users are recommended to be careful when doing so.
</p>
<div class="targetlang"><pre>
&gt; -- example.PI does not exist
&gt; print(example.PI)
nil
-&gt; example.PI=3.142 -- assign failed, example.PI does still not exist
-&gt; print(example.PI)
-nil
-&gt; -- a rawset will work, after this the value is added
-&gt; rawset(example,"PI",3.142)
+&gt; example.PI=3.142 -- new value added
&gt; print(example.PI)
3.142
</pre></div>
@@ -426,7 +445,7 @@ userdata: 003FA320
Like the pointer in the previous section, this is held as a userdata. However, additional features have been added to make this more usable. SWIG creates some accessor/mutator functions <tt>Point_set_x()</tt> and <tt>Point_get_x()</tt>. These will be wrappered, and then added to the metatable added to the userdata. This provides the natural access to the member variables that were shown above (see end of the document for full details).
</p>
<p>
-<tt>const</tt> members of a structure are read-only. Data members can also be forced to be read-only using the immutable directive. As with other immutable's, setting attempts will be silently ignored. For example:
+<tt>const</tt> members of a structure are read-only. Data members can also be forced to be read-only using the immutable directive. As with other immutable's, setting attempts will be cause an error. For example:
</p>
<div class="code"><pre>struct Foo {
...
@@ -999,7 +1018,8 @@ function __newindex(mod,name,value)
if not s then return end
local f=s[name] -- looks for the function
-- calls it to set the value
- if type(f)=="function" then f(value) end
+ if type(f)=="function" then f(value)
+ else rawset(mod,name,value) end
end
</pre></div>
<p>
diff --git a/Examples/lua/variables/runme.lua b/Examples/lua/variables/runme.lua
index 08c24c743..ad0b24ed4 100644
--- a/Examples/lua/variables/runme.lua
+++ b/Examples/lua/variables/runme.lua
@@ -55,15 +55,20 @@ example.print_vars()
print "\nNow I'm going to try and modify some read only variables";
print " Tring to set 'path' to 'Whoa!'";
-example.path = "Whoa!"
-print " This request was silently ignored by Lua. "
-print " But the data has not been changed"
-print("path =", example.path)
+if pcall(function() example.path = "Whoa!" end)==true then
+ print " Thats funny, it didn't give an error!"
+else
+ print " It gave an error, as it should"
+end
+print(" Just checking the value: path =", example.path)
print " Trying to set 'status' to '0'";
- example.status = 0
-print " Again silently ignored"
-print("status =", example.status)
+if pcall(function() example.status = 0 end)==true then
+ print " Thats funny, it didn't give an error!"
+else
+ print " It gave an error, as it should"
+end
+print(" Just checking the value: status =", example.status)
print "\nI'm going to try and update a structure variable.\n"
diff --git a/Examples/test-suite/lua/li_std_string_runme.lua b/Examples/test-suite/lua/li_std_string_runme.lua
index f04d3c165..be43adbe3 100644
--- a/Examples/test-suite/lua/li_std_string_runme.lua
+++ b/Examples/test-suite/lua/li_std_string_runme.lua
@@ -85,8 +85,8 @@ struc=Structure()
assert(type(struc.MemberString2)=="string") -- typemaps make this a string
assert(type(struc.ConstMemberString)=="string")
--- set them
-struc.ConstMemberString="c" -- silently ignored
+-- set a const (should fail with error)
+assert(pcall(function () struc.ConstMemberString="c" end)==false)
--print(struc.MemberString:data(),struc.MemberString2,struc.ConstMemberString:data())
--check type again
@@ -100,9 +100,9 @@ assert(type(struc.ConstMemberString)=="string")
assert(type(li_std_string.Structure_StaticMemberString2)=="string")
assert(type(li_std_string.Structure_ConstStaticMemberString)=="string")
--- try setting
+-- try setting (should fail with error)
--li_std_string.Structure_StaticMemberString2='e'
-li_std_string.Structure_ConstStaticMemberString='f' -- silently ignored
+assert(pcall(function () li_std_string.Structure_ConstStaticMemberString='f' end)==false)
--[[print(li_std_string.Structure_StaticMemberString:data(),
li_std_string.Structure_StaticMemberString2,
li_std_string.Structure_ConstStaticMemberString:data())]]
@@ -111,4 +111,3 @@ li_std_string.Structure_ConstStaticMemberString='f' -- silently ignored
assert(type(li_std_string.Structure_StaticMemberString)=="string")
assert(type(li_std_string.Structure_StaticMemberString2)=="string")
assert(type(li_std_string.Structure_ConstStaticMemberString)=="string")
-
diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg
index c08f3ea54..9e2b4be7d 100644
--- a/Lib/lua/luarun.swg
+++ b/Lib/lua/luarun.swg
@@ -125,13 +125,27 @@ typedef struct {
#ifdef __cplusplus
/* Special helper for member function pointers
it gets the address, casts it, then dereferences it */
-#define SWIG_mem_fn_as_voidptr(a) (*((char**)&(a)))
+//#define SWIG_mem_fn_as_voidptr(a) (*((char**)&(a)))
#endif
/* -----------------------------------------------------------------------------
* global variable support code: modules
* ----------------------------------------------------------------------------- */
+/* this function is called when trying to set an immutable.
+default value is to print an error.
+This can removed with a compile flag SWIGLUA_IGNORE_SET_IMMUTABLE */
+SWIGINTERN int SWIG_Lua_set_immutable(lua_State* L)
+{
+/* there should be 1 param passed in: the new value */
+#ifndef SWIGLUA_IGNORE_SET_IMMUTABLE
+ lua_pop(L,1); /* remove it */
+ lua_pushstring(L,"This variable is immutable");
+ lua_error(L);
+#endif
+ return 0; /* should not return anything */
+}
+
/* the module.get method used for getting linked data */
SWIGINTERN int SWIG_Lua_module_get(lua_State* L)
{
@@ -192,10 +206,11 @@ SWIGINTERN int SWIG_Lua_module_set(lua_State* L)
lua_call(L,1,0);
return 0;
}
- lua_pop(L,1); /* remove the top */
}
- lua_pop(L,1); /* remove the .set */
- return 0;
+ lua_settop(L,3); /* reset back to start */
+ /* we now have the table, key & new value, so just set directly */
+ lua_rawset(L,1); /* add direct */
+ return 0;
}
/* registering a module in lua */
diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx
index 20efd67a5..f1730776c 100644
--- a/Source/Modules/lua.cxx
+++ b/Source/Modules/lua.cxx
@@ -678,18 +678,27 @@ only WRT this variable will look into this later.
NEW LANGUAGE NOTE:END ************************************************/
REPORT("variableWrapper", n);
String *iname = Getattr(n, "sym:name");
- SwigType *type = Getattr(n, "type");
// let SWIG generate the wrappers
int result = Language::variableWrapper(n);
// normally SWIG will generate 2 wrappers, a get and a set
// but in certain scenarios (immutable, or if its arrays), it will not
String *getName = Swig_name_wrapper(Swig_name_get(iname));
String *setName = 0;
- if (is_assignable(n) == false || SwigType_isarray(type)) {
- // TODO: how about calling a 'this is not settable' error message?
- setName = NewString("0");
- } else {
+ // checking whether it can be set to or not appears to be a very error prone issue
+ // I refered to the Language::variableWrapper() to find this out
+ bool assignable=is_assignable(n);
+ SwigType *type = Getattr(n, "type");
+ String *tm = Swig_typemap_lookup_new("globalin", n, iname, 0);
+ if (!tm && SwigType_isarray(type))
+ assignable=false;
+ Delete(tm);
+
+ if (assignable) {
setName = Swig_name_wrapper(Swig_name_set(iname));
+ } else {
+ // TODO: how about calling a 'this is not settable' error message?
+ setName = NewString("SWIG_Lua_set_immutable"); // error message
+ //setName = NewString("0");
}
// register the variable
Printf(s_var_tab, "%s{ \"%s\", %s, %s },\n", tab4, iname, getName, setName);
@@ -960,20 +969,19 @@ NEW LANGUAGE NOTE:END ************************************************/
virtual int membervariableHandler(Node *n) {
// REPORT("membervariableHandler",n);
String *symname = Getattr(n, "sym:name");
- String *rname;
+ String *gname, *sname;
Language::membervariableHandler(n);
- Printv(s_attr_tab, tab4, "{ \"", symname, "\",", NIL);
- rname = Swig_name_wrapper(Swig_name_get(Swig_name_member(class_name, symname)));
- Printv(s_attr_tab, rname, ", ", NIL);
- Delete(rname);
+ gname = Swig_name_wrapper(Swig_name_get(Swig_name_member(class_name, symname)));
if (!GetFlag(n, "feature:immutable")) {
- rname = Swig_name_wrapper(Swig_name_set(Swig_name_member(class_name, symname)));
- Printv(s_attr_tab, rname, "},\n", NIL);
- Delete(rname);
+ sname = Swig_name_wrapper(Swig_name_set(Swig_name_member(class_name, symname)));
} else {
- Printf(s_attr_tab, "0 },\n");
+ //sname = NewString("0");
+ sname = NewString("SWIG_Lua_set_immutable"); // error message
}
+ Printf(s_attr_tab,"%s{ \"%s\", %s, %s},\n",tab4,symname,gname,sname);
+ Delete(gname);
+ Delete(sname);
return SWIG_OK;
}