Author: fperrad Date: Sun Jan 15 22:59:02 2006 New Revision: 11206 Modified: trunk/languages/lua/classes/luatable.pmc Log: Lua :
this patch changes the behaviour of the LuaTable PMC. changes have to do with the reference semantics that PMCs have, and LuaTables should not have. Setting and getting a value now will set (and get) a copy of the value. Clone() returns a reference to itself, as clone() should be used for register to register copying (due to the by-value semantics of Lua values) Courtesy of Klaas-Jan Stol. Modified: trunk/languages/lua/classes/luatable.pmc ============================================================================== --- trunk/languages/lua/classes/luatable.pmc (original) +++ trunk/languages/lua/classes/luatable.pmc Sun Jan 15 22:59:02 2006 @@ -71,6 +71,25 @@ Return the string "table". /* +=item C<PMC* clone()> + +PMCs are always handled by-reference in Parrot. So, copying register contents only copies +the reference to the PMC. For LuaString, LuaNumber, LuaBoolean, this is not correct, +as Lua has by-value semantics for these types. In order to be able to handle register +"move" instructions, this should be implemented using clone(). However, LuaTable and LuaFunction +do have by-reference semantics. As you don't know the type during compile-time of an object, +just always use clone() to copy register contents. LuaTable and LuaFunction should therefore +only clone the reference to themselves, not make a deep copy. + +=cut + +*/ + PMC* clone() { + return SELF; + } + +/* + =item C<INTVAL get_bool()> In Lua, both C<nil> and C<false> make a condition false; any other values @@ -91,16 +110,25 @@ So return always true. C<table> accessor. +A copy of the value is retrieved, otherwise, this could happen: + + temp = table[key] + temp = <some other value> + temp2 = table[key] + # temp2 is now <some other value> due to the by-reference semantics of PMCs + =cut */ PMC* get_pmc_keyed (PMC* key) { + PMC *newcopy; PMC *retval = SUPER(key); if (enum_class_None == retval->vtable->base_type) { - return Lua_Nil; + return Lua_Nil; /* should we create a New LuaNil object every time? Or is returning the same LuaNil over and over again ok? */ } - return retval; + newcopy = retval->vtable->clone(INTERP, retval); + return newcopy; } /* @@ -109,17 +137,29 @@ C<table> accessor. C<table> mutator. +A copy of the value is stored, otherwise, this could happen: + + table[key] = value + value = <some other value> + temp = table[key] + # temp is now <some other value> due to the by-reference semantics of PMCs + =cut */ void set_pmc_keyed (PMC* key, PMC* value) { + + /* XXX should check for "isa", not equality with "==", since LuaNil is no singular anymore */ + if (key == Lua_Nil) { real_exception(INTERP, NULL, 1, "table index is nil"); } if (value == Lua_Nil) { Hash.SELF.delete_keyed(key); - } else { - SUPER(key, value); + } + else { + PMC *newcopy = value->vtable->clone(INTERP, value); + SUPER(key, newcopy); } } @@ -152,6 +192,8 @@ Return always false. return (PMC*)0; } + /* TODO: Implement the Metamethod mechanism, see the Lua ref.man. */ + PMC* subtract (PMC* value, PMC* dest) { return (PMC*)0; }