/OLD.SharpLua/SharpLua/LuaTypes/LuaClass.cs

http://github.com/mlnlover11/SharpLua · C# · 329 lines · 277 code · 28 blank · 24 comment · 54 complexity · 4e04869c2bb2ce13eac4f4945ad25e39 MD5 · raw file

  1. /*
  2. * Created by SharpDevelop.
  3. * User: elijah
  4. * Date: 12/23/2011
  5. * Time: 12:35 PM
  6. *
  7. * To change this template use Tools | Options | Coding | Edit Standard Headers.
  8. */
  9. using System;
  10. using System.Collections.Generic;
  11. using SharpLua.Library;
  12. namespace SharpLua.LuaTypes
  13. {
  14. /// <summary>
  15. /// A Lua class
  16. /// </summary>
  17. [Serializable()]
  18. public class LuaClass : LuaValue
  19. {
  20. private static List<string> classNames = new List<string>();
  21. public bool Final = false;
  22. public bool Static = false;
  23. private string _name = "";
  24. public string Name
  25. {
  26. get
  27. {
  28. return _name;
  29. }
  30. set
  31. {
  32. _name = Rename(value);
  33. }
  34. }
  35. public List<LuaClass> ParentClasses = new List<LuaClass>();
  36. public List<LuaClass> ChildClasses = new List<LuaClass>();
  37. public LuaFunction IndexFunction;
  38. public LuaFunction NewIndexFunction;
  39. public LuaFunction CallFunction;
  40. public LuaFunction ToStringFunction;
  41. public LuaFunction Constructor;
  42. public LuaFunction Destructor;
  43. public LuaTable Self;
  44. public LuaClass(string name, bool final, bool _static)
  45. {
  46. this.Name = Rename(name);
  47. this.Final = final;
  48. this.Static = _static;
  49. this.IndexFunction = new LuaFunction(new LuaFunc((LuaValue[] args) =>
  50. {return null; }));
  51. this.CallFunction = new LuaFunction(new LuaFunc((LuaValue[] args) =>
  52. {return null; }));
  53. this.NewIndexFunction = new LuaFunction(new LuaFunc((LuaValue[] args) =>
  54. {return null; }));
  55. this.ToStringFunction = new LuaFunction(new LuaFunc((LuaValue[] args) =>
  56. {return new LuaString("Lua Class: " + GetHashCode() + ", Name: " + Name); }));
  57. this.Constructor = new LuaFunction(new LuaFunc((LuaValue[] args) =>
  58. {
  59. // do nothing
  60. return LuaNil.Nil;
  61. }));
  62. this.Destructor = new LuaFunction(new LuaFunc((LuaValue[] args) =>
  63. {
  64. // do nothing
  65. return LuaNil.Nil;
  66. }));
  67. this.Self = new LuaTable();
  68. Self.Register("new", New);
  69. Self.Register("Set", Set);
  70. Self.Register("HasMember", HasMember);
  71. Self.Register("Inherits", Inherits);
  72. Self.Register("IsParentOf", IsParentOf);
  73. Self.Register("GetParentClasses", GetParentClasses);
  74. Self.Register("GetChildClasses", GetChildClasses);
  75. Self.Register("CallParentMethod", CallParentMethod);
  76. Self.Register("CreateSubclass", CreateSubClass);
  77. Self.Register("CallMethod", CallMethod);
  78. Self.Register("GetTable", GetTable);
  79. GenerateMetaTable();
  80. }
  81. public override object Value {
  82. get {
  83. return Self;
  84. }
  85. }
  86. public override string GetTypeCode()
  87. {
  88. return "class";
  89. }
  90. public LuaValue New(LuaValue[] args)
  91. {
  92. if (Static)
  93. throw new Exception("Cannot create an instance of a static class!");
  94. LuaClass n = ClassLib.CreateInstance(new LuaValue[] {this }) as LuaClass;
  95. n.Constructor.Invoke(args);
  96. return n;
  97. }
  98. public LuaValue Set(LuaValue[] args)
  99. {
  100. for (int i = 1; i < args.Length; i++)
  101. TableLib.Copy(new LuaValue[] {Self, args[i]});
  102. return Self;
  103. }
  104. public LuaValue HasMember(LuaValue[] args)
  105. { //(m)
  106. return ClassLib.IsMemberOf(new LuaValue[] {args[0], this});
  107. }
  108. public LuaValue Inherits(LuaValue[] args)
  109. { //(_class)
  110. foreach (LuaClass c in this.ParentClasses)
  111. {
  112. if (Name == c.Name)
  113. return LuaBoolean.True;
  114. }
  115. return LuaBoolean.False;
  116. }
  117. public LuaValue IsParentOf(LuaValue[] args)
  118. {
  119. LuaClass _class = args[0] as LuaClass;
  120. foreach (LuaClass c in ChildClasses)
  121. if (c.Name == _class.Name)
  122. return LuaBoolean.True;
  123. return LuaBoolean.False;
  124. }
  125. public LuaValue GetTable(LuaValue[] args)
  126. {
  127. return Self;
  128. }
  129. public LuaValue GetParentClasses(LuaValue[] args)
  130. {
  131. LuaTable t = new LuaTable();
  132. foreach (LuaClass p in ParentClasses)
  133. t.AddValue(p);
  134. return t;
  135. }
  136. public LuaValue GetChildClasses(LuaValue[] args)
  137. {
  138. List<LuaClass> c = new List<LuaClass>();
  139. foreach (LuaClass p in ChildClasses)
  140. c.Add(p);
  141. return new LuaMultiValue(c.ToArray());
  142. }
  143. public LuaValue CallParentMethod(LuaValue[] args)
  144. {
  145. //method, ...
  146. string method = args[0].Value.ToString();
  147. // strip method name
  148. List<LuaValue> args2 = new List<LuaValue>();
  149. foreach (LuaValue a in args)
  150. args2.Add(a);
  151. args2.RemoveAt(0);
  152. LuaFunction func = InternalCallParentMethod(method) as LuaFunction;
  153. if (func == null)
  154. throw new Exception("Cannot find function '" + method + "'!");
  155. else
  156. return func.Invoke(args2.ToArray());
  157. }
  158. public LuaValue InternalCallParentMethod(string method)
  159. {
  160. LuaValue m = LuaNil.Nil;
  161. if (ParentClasses.Count > 0)
  162. {
  163. foreach (LuaClass c in ParentClasses)
  164. {
  165. m = ClassLib.FindMethod(new LuaValue[] {new LuaString(method), c});
  166. if (m != null)
  167. break;
  168. }
  169. }
  170. if (m == LuaNil.Nil)
  171. for (int i = 0;i < ParentClasses.Count; i++)
  172. m = ParentClasses[i].InternalCallParentMethod(method);
  173. return m;
  174. }
  175. // creates a subclass inheriting all args except arg[1] if its a table
  176. // e.g. x = c:CreateSubclass()
  177. public LuaValue CreateSubClass(LuaValue[] args)
  178. {
  179. List<LuaValue> args2 = new List<LuaValue>();
  180. foreach (LuaValue a in args)
  181. {
  182. args2.Add(a);
  183. }
  184. args2.Add(this);
  185. return ClassLib.CreateClass(args);
  186. }
  187. public LuaValue CallMethod(LuaValue[] args)
  188. {
  189. //(func, ...)
  190. // strip method name
  191. string func = args[0].Value.ToString();
  192. List<LuaValue> args2 = new List<LuaValue>();
  193. if ((args[1] as LuaUserdata) != null)
  194. {
  195. foreach (LuaValue a in ((args[1] as LuaUserdata).Value as LuaValue[]))
  196. args2.Add(a);
  197. }
  198. else
  199. {
  200. foreach (LuaValue a in args)
  201. args2.Add(a);
  202. }
  203. try
  204. {
  205. args2.RemoveAt(0);
  206. }
  207. catch
  208. {
  209. }
  210. LuaFunction f = ClassLib.FindMethod(new LuaValue[] {new LuaString(func), this}) as LuaFunction;
  211. if ((f == null))
  212. f = InternalCallParentMethod(func) as LuaFunction;
  213. // if its still LuaNil.Nil then throw an error
  214. if ((f == null))
  215. throw new Exception("Cannot find function '" + func + "'!");
  216. return f.Invoke(args2.ToArray());
  217. }
  218. public override string ToString()
  219. {
  220. return ToStringFunction.Invoke(new LuaValue[] {}).ToString();
  221. }
  222. public LuaValue GetObject(LuaValue key, LuaClass p)
  223. {
  224. if ((p.Self.RawGetValue(key) != null) && (p.Self.RawGetValue(key) != LuaNil.Nil))
  225. return p.Self.RawGetValue(key);
  226. else
  227. {
  228. foreach (LuaClass c in p.ParentClasses)
  229. return GetObject(key, c);
  230. }
  231. return LuaNil.Nil;
  232. }
  233. public void GenerateMetaTable()
  234. {
  235. Self.MetaTable = new LuaTable();
  236. Self.MetaTable.Register("__index",new LuaFunc(delegate(LuaValue[] args)
  237. { //(table, key)
  238. LuaValue key = args[0];
  239. IndexFunction.Invoke(new LuaValue[] {Self, key}); // user defined __index function
  240. // attempt to get from parents also
  241. return GetObject(key, this); //CallMethod(new LuaValue[] {key});
  242. }));
  243. Self.MetaTable.Register("__call", new LuaFunc(delegate(LuaValue[] args)
  244. { //(func, ...)
  245. if (args.Length == 0)
  246. return LuaNil.Nil;
  247. List<LuaValue> args2 = new List<LuaValue>();
  248. foreach (LuaValue a in args)
  249. args2.Add(a);
  250. args2.RemoveAt(0);
  251. CallFunction.Invoke(new LuaValue[] {args[0], new LuaMultiValue(args2.ToArray())}); // user defined __call function
  252. return CallMethod(new LuaValue[] {args[0], new LuaUserdata(args2.ToArray())}); // call function
  253. }));
  254. Self.MetaTable.Register("__newindex",new LuaFunc(delegate(LuaValue[] args)
  255. {
  256. LuaValue key = args[1];
  257. LuaValue value = args[2];
  258. //(table, key, value)
  259. NewIndexFunction.Invoke(new LuaValue[] {Self, key, value}); // user defined __newindex function
  260. // check for user defined "metamethods"
  261. string obj = key.Value.ToString();
  262. if (obj == "__index")
  263. {
  264. // assign this to the __indexfunction variable
  265. IndexFunction = value as LuaFunction;
  266. }
  267. else if (obj == "__newindex")
  268. NewIndexFunction = value as LuaFunction;
  269. else if (obj == "__call")
  270. CallFunction = value as LuaFunction;
  271. else if (obj == "__tostring")
  272. ToStringFunction = value as LuaFunction;
  273. else if (obj == "final")
  274. Final = true;
  275. else if (obj == "static")
  276. Static = true;
  277. else if (obj == "name")
  278. Name = Rename(value.Value.ToString());
  279. else if (obj == "constructor")
  280. Constructor = (LuaFunction) value;
  281. else if (obj == "destructor")
  282. Destructor = (LuaFunction) value;
  283. else // its a normal key/value pair
  284. Self.SetKeyValue(key, value);
  285. return LuaNil.Nil;
  286. }));
  287. Self.MetaTable.Register("__tostring", new LuaFunc(delegate(LuaValue[] args)
  288. {
  289. return ToStringFunction.Invoke(new LuaValue[] {});
  290. }));
  291. this.MetaTable = Self.MetaTable;
  292. }
  293. string Rename(string val)
  294. {
  295. classNames.Remove(this.Name);
  296. if (classNames.Contains(val))
  297. throw new Exception("Class '" + val + "' is already defined!");
  298. return val;
  299. }
  300. }
  301. }