diff --git a/src/core/org/luaj/vm2/LuaTable.java b/src/core/org/luaj/vm2/LuaTable.java index df706230..8201333c 100644 --- a/src/core/org/luaj/vm2/LuaTable.java +++ b/src/core/org/luaj/vm2/LuaTable.java @@ -119,9 +119,34 @@ public class LuaTable extends LuaValue { if ( m_metatable!=null && !m_metatable.rawget(METATABLE).isnil() ) error("cannot change a protected metatable"); m_metatable = metatable; + LuaValue mode; + if ( m_metatable!=null && (mode=m_metatable.rawget(MODE)).isstring() ) { + String m = mode.toString(); + return changemode(m.contains("k"),m.contains("v")); + } return this; } + protected LuaTable changemode(boolean weakkeys, boolean weakvalues) { + if ( weakkeys || weakvalues ) { + return recreateas(weakkeys, weakvalues); + } + return this; + } + + protected LuaTable recreateas(boolean weakkeys, boolean weakvalues) { + LuaTable t = weakkeys||weakvalues? + new WeakTable(weakkeys, weakvalues): + new LuaTable(); + t.presize(array.length,hashKeys.length); + Varargs n; + LuaValue k = NIL; + while ( !(k = ((n = next(k)).arg1())).isnil() ) + t.rawset(k, n.arg(2)); + t.m_metatable = m_metatable; + return t; + } + public LuaValue get( int key ) { LuaValue v = rawget(key); return v.isnil() && m_metatable!=null? gettable(this,valueOf(key)): v; diff --git a/src/core/org/luaj/vm2/LuaValue.java b/src/core/org/luaj/vm2/LuaValue.java index 022ceb3d..b46d238e 100644 --- a/src/core/org/luaj/vm2/LuaValue.java +++ b/src/core/org/luaj/vm2/LuaValue.java @@ -298,8 +298,7 @@ public class LuaValue extends Varargs { // lua number/string conversion public LuaString strvalue() { typerror("strValue"); return null; } - public LuaValue strongvalue() { return this; } - + public LuaValue strongvalue() { return this; } // conversion from java values public static LuaBoolean valueOf(boolean b) { return b? LuaValue.TRUE: FALSE; }; diff --git a/src/core/org/luaj/vm2/WeakTable.java b/src/core/org/luaj/vm2/WeakTable.java index 3b320650..4514c5b1 100644 --- a/src/core/org/luaj/vm2/WeakTable.java +++ b/src/core/org/luaj/vm2/WeakTable.java @@ -38,36 +38,41 @@ public class WeakTable extends LuaTable { ref = new WeakReference(val); } public int type() { - return LuaValue.TNIL; + return strongvalue().type(); } public String typename() { - return "value"; + return "weakvalue"; } public LuaValue strongvalue() { Object o = ref.get(); return o!=null? (LuaValue)o: NIL; } + public String toString() { + return strongvalue().toString(); + } } private static class WeakUserdata extends LuaValue { - private final WeakReference ref; - private LuaValue metatable; + private WeakReference ref; + private WeakReference mt; public WeakUserdata(Object val, LuaValue metatable) { - ref = new WeakReference(val); + this.ref = new WeakReference(val); + this.mt = new WeakReference(metatable); } public int type() { - return LuaValue.TNIL; + return TVALUE; } public String typename() { - return "value"; + return "weakuserdata"; } public LuaValue strongvalue() { - Object o = ref.get(); - if ( o == null ) { - metatable = null; - return NIL; + if ( ref != null ) { + Object o = ref.get(); + if ( o != null ) + return userdataOf( o, (LuaValue) mt.get() ); } - return userdataOf( o, metatable ); + ref = mt = null; + return NIL; } } @@ -135,7 +140,7 @@ public class WeakTable extends LuaTable { v = v.strongvalue(); if ( v.isnil() ) { // TODO: mark table for culling? - rawset(key, NIL); + super.rawset(key, NIL); } return v; } @@ -147,7 +152,7 @@ public class WeakTable extends LuaTable { v = v.strongvalue(); if ( v.isnil() ) { // TODO: mark table for culling? - rawset(key, NIL); + super.rawset(key, NIL); } return v; } @@ -176,4 +181,12 @@ public class WeakTable extends LuaTable { } } } + + protected LuaTable changemode(boolean k, boolean v) { + if ( k!=this.weakKeys || v!=weakValues ) + return recreateas(k,v); + return this; + } + + } diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index 081edffa..3982ddcb 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -317,8 +317,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { case 13: { // "setmetatable", // (table, metatable) -> table final LuaValue t = args.arg1(); final LuaValue mt = args.checkvalue(2); - t.setmetatable(mt.isnil()? null: mt.checktable()); - return t; + return t.setmetatable(mt.isnil()? null: mt.checktable()); } case 14: { // "tostring", // (e) -> value LuaValue arg = args.checkvalue(1);