internal DynamicLuaTable(LuaTable table, Lua state, string path = null) : base() { this._table = table; this._state = state; if (path == null) { path = LuaHelper.GetRandomString(); //tables need a name, so we can access them } this._path = path; }
public dynamic Power(object operand) { operand = LuaHelper.WrapObject(operand, _state); var func = GetMetaFunction("pow"); if (func != null) { return(func.Call(_table, operand)); } throw new InvalidOperationException("Metamethod __pow not found"); }
public override bool TryGetMember(GetMemberBinder binder, out object result) { result = null; if (!int.TryParse(binder.Name, out var index)) { return(false); } if (index >= _array.Length) { return(false); } result = LuaHelper.UnWrapObject(_array[index], _state); return(true); }
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { result = null; if (!int.TryParse(indexes[0].ToString(), out var index)) { return(false); } if (index >= _array.Length) { return(false); } result = LuaHelper.UnWrapObject(_array[index], _state); return(true); }
private object GetTableValue(string name) { var val = _table[name]; if (val != null) { return(LuaHelper.UnWrapObject(val, _state, _path + "." + name)); } //not found, check __index of metatable var func = GetMetaFunction("index"); if (func != null) //metatable and metamethod set { return(LuaHelper.UnWrapObject(func.Call(_table, name)[0], _state, _path + "." + name)); } return(null); }
private void SetTableMember(string name, object value) { var tmp = LuaHelper.WrapObject(value, _state, _path + "." + name); if (tmp == null) { return; } var func = GetMetaFunction("newindex"); if (func != null) { func.Call(_table, name, value); } else { _table[name] = value; } }
private object GetLuaValue(string name) { return(LuaHelper.UnWrapObject(Lua[name], Lua, name)); }
public dynamic GetMetatable() { return(LuaHelper.UnWrapObject( _state.DoString($"return getmetatable({_path})", "DynamicLua internal operation")[0], _state)); }
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result) { string metamethodName; var switchOperands = false; //Lua has only comparison metamethods for less, so for greater the we have to switch the operands var negateResult = false; //Lua has only metamethods for equal, so we need this trick here. switch (binder.Operation) { //Math case ExpressionType.Add: case ExpressionType.AddChecked: case ExpressionType.AddAssign: case ExpressionType.AddAssignChecked: //TODO: Thing about __concat metamethodName = "add"; break; case ExpressionType.Subtract: case ExpressionType.SubtractChecked: case ExpressionType.SubtractAssign: case ExpressionType.SubtractAssignChecked: metamethodName = "sub"; break; case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: case ExpressionType.MultiplyAssign: case ExpressionType.MultiplyAssignChecked: metamethodName = "mul"; break; case ExpressionType.Divide: case ExpressionType.DivideAssign: metamethodName = "div"; break; case ExpressionType.Modulo: case ExpressionType.ModuloAssign: metamethodName = "mod"; break; case ExpressionType.Power: case ExpressionType.PowerAssign: metamethodName = "pow"; break; //Logic Tests case ExpressionType.Equal: metamethodName = "eq"; break; case ExpressionType.NotEqual: metamethodName = "eq"; negateResult = true; break; case ExpressionType.GreaterThan: metamethodName = "lt"; switchOperands = true; break; case ExpressionType.GreaterThanOrEqual: metamethodName = "le"; switchOperands = true; break; case ExpressionType.LessThan: metamethodName = "lt"; break; case ExpressionType.LessThanOrEqual: metamethodName = "le"; break; default: //This operation is not supported by Lua... result = null; return(false); } var mtFunc = GetMetaFunction(metamethodName); if (mtFunc == null) { result = null; return(false); } if (!switchOperands) { //Metamethods just return one value, or the other will be ignored anyway result = mtFunc.Call(_table, LuaHelper.WrapObject(arg, _state)) [0]; } else { result = mtFunc.Call(LuaHelper.WrapObject(arg, _state), _table)[0]; } //We can't negate if its not bool. If the metamethod returned someting other than bool and ~= is called there will be a bug. (But who would do this?) if (negateResult && result is bool b) { result = !b; } return(true); }