/// <summary> /// Attempts to invoke a meta-method and returns the result. /// </summary> /// <param name="type">The type of operation.</param> /// <param name="other">The other value.</param> /// <returns>The result of the meta-method, or null if not found.</returns> internal static ILuaValue AttempMetamethod(BinaryOperationType type, ILuaValue self, ILuaValue other) { if (type == BinaryOperationType.And || type == BinaryOperationType.Or) { return(null); } // Search the first object. ILuaValue ret = null; var self2 = self as ILuaTable; if (self2 != null && self2.MetaTable != null) { var t = self2.MetaTable.GetItemRaw(LuaString._metamethods[type]); if (t != null) { ret = t.Invoke(LuaNil.Nil, false, -1, new LuaMultiValue(self, other)); } else if (type == BinaryOperationType.Lte || type == BinaryOperationType.Gt) { t = self2.MetaTable.GetItemRaw(LuaString._metamethods[BinaryOperationType.Lt]); if (t != null) { ret = t.Invoke(LuaNil.Nil, false, -1, new LuaMultiValue(other, self)).Not(); } } } // Search the second object. var other2 = other as ILuaTable; if (ret == null && other2 != null && other2.MetaTable != null) { var t = other2.MetaTable.GetItemRaw(LuaString._metamethods[type]); if (t != null) { ret = t.Invoke(LuaNil.Nil, true, -1, new LuaMultiValue(self, other)); } else if (type == BinaryOperationType.Lte || type == BinaryOperationType.Gt) { t = other2.MetaTable.GetItemRaw(LuaString._metamethods[BinaryOperationType.Lt]); if (t != null) { ret = t.Invoke(LuaNil.Nil, true, -1, new LuaMultiValue(other, self)).Not(); } } } // Fix the arguments for comparisons. if (ret != null) { ret = ret.Single(); switch (type) { case BinaryOperationType.Gt: case BinaryOperationType.Gte: case BinaryOperationType.NotEquals: ret = LuaBoolean.Create(!ret.IsTrue); break; case BinaryOperationType.Equals: case BinaryOperationType.Lt: case BinaryOperationType.Lte: ret = LuaBoolean.Create(ret.IsTrue); break; } } return(ret); }