candle 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. data/LICENSE.txt +20 -0
  2. data/README.md +4 -0
  3. data/VERSION +1 -0
  4. data/bin/candle +21 -0
  5. data/lib/candle.rb +68 -0
  6. data/lib/candle/command.rb +27 -0
  7. data/lib/candle/generators/actions.rb +183 -0
  8. data/lib/candle/generators/blank.rb +127 -0
  9. data/lib/candle/generators/cli.rb +55 -0
  10. data/lib/candle/generators/help.rb +47 -0
  11. data/lib/candle/generators/jam.rb +80 -0
  12. data/lib/candle/generators/lua/scripts/AppDelegate.lua +36 -0
  13. data/lib/candle/generators/lua/scripts/tests/init.lua +6 -0
  14. data/lib/candle/generators/lua/scripts/tests/someTest.lua +12 -0
  15. data/lib/candle/generators/lua/wax/ProtocolLoader.h +12 -0
  16. data/lib/candle/generators/lua/wax/bin/hammer +157 -0
  17. data/lib/candle/generators/lua/wax/bin/update-xibs +131 -0
  18. data/lib/candle/generators/lua/wax/bin/waxsim +0 -0
  19. data/lib/candle/generators/lua/wax/lib/build-scripts/compile-stdlib.sh +14 -0
  20. data/lib/candle/generators/lua/wax/lib/build-scripts/copy-scripts.sh +58 -0
  21. data/lib/candle/generators/lua/wax/lib/build-scripts/luac.lua +80 -0
  22. data/lib/candle/generators/lua/wax/lib/extensions/CGAffine/wax_CGTransform.h +12 -0
  23. data/lib/candle/generators/lua/wax/lib/extensions/CGAffine/wax_CGTransform.m +85 -0
  24. data/lib/candle/generators/lua/wax/lib/extensions/CGContext/wax_CGContext.h +12 -0
  25. data/lib/candle/generators/lua/wax/lib/extensions/CGContext/wax_CGContext.m +251 -0
  26. data/lib/candle/generators/lua/wax/lib/extensions/HTTP/wax_http.h +14 -0
  27. data/lib/candle/generators/lua/wax/lib/extensions/HTTP/wax_http.m +240 -0
  28. data/lib/candle/generators/lua/wax/lib/extensions/HTTP/wax_http_connection.h +54 -0
  29. data/lib/candle/generators/lua/wax/lib/extensions/HTTP/wax_http_connection.m +304 -0
  30. data/lib/candle/generators/lua/wax/lib/extensions/filesystem/wax_filesystem.h +9 -0
  31. data/lib/candle/generators/lua/wax/lib/extensions/filesystem/wax_filesystem.m +273 -0
  32. data/lib/candle/generators/lua/wax/lib/extensions/json/Rakefile +10 -0
  33. data/lib/candle/generators/lua/wax/lib/extensions/json/wax_json.c +304 -0
  34. data/lib/candle/generators/lua/wax/lib/extensions/json/wax_json.h +11 -0
  35. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl-1.0.9.tar.gz +0 -0
  36. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/api/yajl_common.h +85 -0
  37. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/api/yajl_gen.h +159 -0
  38. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/api/yajl_parse.h +193 -0
  39. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl.c +159 -0
  40. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_alloc.c +65 -0
  41. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_alloc.h +50 -0
  42. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_buf.c +119 -0
  43. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_buf.h +73 -0
  44. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_bytestack.h +85 -0
  45. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_common.h +85 -0
  46. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_encode.c +188 -0
  47. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_encode.h +50 -0
  48. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_gen.c +322 -0
  49. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_gen.h +159 -0
  50. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_lex.c +737 -0
  51. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_lex.h +133 -0
  52. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_parse.h +193 -0
  53. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_parser.c +448 -0
  54. data/lib/candle/generators/lua/wax/lib/extensions/json/yajl/yajl_parser.h +82 -0
  55. data/lib/candle/generators/lua/wax/lib/lua/lapi.c +1087 -0
  56. data/lib/candle/generators/lua/wax/lib/lua/lapi.h +16 -0
  57. data/lib/candle/generators/lua/wax/lib/lua/lauxlib.c +652 -0
  58. data/lib/candle/generators/lua/wax/lib/lua/lauxlib.h +174 -0
  59. data/lib/candle/generators/lua/wax/lib/lua/lbaselib.c +653 -0
  60. data/lib/candle/generators/lua/wax/lib/lua/lcode.c +839 -0
  61. data/lib/candle/generators/lua/wax/lib/lua/lcode.h +76 -0
  62. data/lib/candle/generators/lua/wax/lib/lua/ldblib.c +397 -0
  63. data/lib/candle/generators/lua/wax/lib/lua/ldebug.c +638 -0
  64. data/lib/candle/generators/lua/wax/lib/lua/ldebug.h +33 -0
  65. data/lib/candle/generators/lua/wax/lib/lua/ldo.c +518 -0
  66. data/lib/candle/generators/lua/wax/lib/lua/ldo.h +57 -0
  67. data/lib/candle/generators/lua/wax/lib/lua/ldump.c +164 -0
  68. data/lib/candle/generators/lua/wax/lib/lua/lfunc.c +174 -0
  69. data/lib/candle/generators/lua/wax/lib/lua/lfunc.h +34 -0
  70. data/lib/candle/generators/lua/wax/lib/lua/lgc.c +711 -0
  71. data/lib/candle/generators/lua/wax/lib/lua/lgc.h +110 -0
  72. data/lib/candle/generators/lua/wax/lib/lua/linit.c +38 -0
  73. data/lib/candle/generators/lua/wax/lib/lua/liolib.c +553 -0
  74. data/lib/candle/generators/lua/wax/lib/lua/llex.c +461 -0
  75. data/lib/candle/generators/lua/wax/lib/lua/llex.h +81 -0
  76. data/lib/candle/generators/lua/wax/lib/lua/llimits.h +128 -0
  77. data/lib/candle/generators/lua/wax/lib/lua/lmathlib.c +263 -0
  78. data/lib/candle/generators/lua/wax/lib/lua/lmem.c +86 -0
  79. data/lib/candle/generators/lua/wax/lib/lua/lmem.h +49 -0
  80. data/lib/candle/generators/lua/wax/lib/lua/loadlib.c +666 -0
  81. data/lib/candle/generators/lua/wax/lib/lua/lobject.c +214 -0
  82. data/lib/candle/generators/lua/wax/lib/lua/lobject.h +381 -0
  83. data/lib/candle/generators/lua/wax/lib/lua/lopcodes.c +102 -0
  84. data/lib/candle/generators/lua/wax/lib/lua/lopcodes.h +268 -0
  85. data/lib/candle/generators/lua/wax/lib/lua/loslib.c +243 -0
  86. data/lib/candle/generators/lua/wax/lib/lua/lparser.c +1339 -0
  87. data/lib/candle/generators/lua/wax/lib/lua/lparser.h +82 -0
  88. data/lib/candle/generators/lua/wax/lib/lua/lstate.c +214 -0
  89. data/lib/candle/generators/lua/wax/lib/lua/lstate.h +169 -0
  90. data/lib/candle/generators/lua/wax/lib/lua/lstring.c +111 -0
  91. data/lib/candle/generators/lua/wax/lib/lua/lstring.h +31 -0
  92. data/lib/candle/generators/lua/wax/lib/lua/lstrlib.c +869 -0
  93. data/lib/candle/generators/lua/wax/lib/lua/ltable.c +588 -0
  94. data/lib/candle/generators/lua/wax/lib/lua/ltable.h +40 -0
  95. data/lib/candle/generators/lua/wax/lib/lua/ltablib.c +287 -0
  96. data/lib/candle/generators/lua/wax/lib/lua/ltm.c +75 -0
  97. data/lib/candle/generators/lua/wax/lib/lua/ltm.h +54 -0
  98. data/lib/candle/generators/lua/wax/lib/lua/lua.h +388 -0
  99. data/lib/candle/generators/lua/wax/lib/lua/luaconf.h +753 -0
  100. data/lib/candle/generators/lua/wax/lib/lua/lualib.h +53 -0
  101. data/lib/candle/generators/lua/wax/lib/lua/lundump.c +227 -0
  102. data/lib/candle/generators/lua/wax/lib/lua/lundump.h +36 -0
  103. data/lib/candle/generators/lua/wax/lib/lua/lvm.c +763 -0
  104. data/lib/candle/generators/lua/wax/lib/lua/lvm.h +36 -0
  105. data/lib/candle/generators/lua/wax/lib/lua/lzio.c +82 -0
  106. data/lib/candle/generators/lua/wax/lib/lua/lzio.h +67 -0
  107. data/lib/candle/generators/lua/wax/lib/lua/print.c +227 -0
  108. data/lib/candle/generators/lua/wax/lib/project.rake +159 -0
  109. data/lib/candle/generators/lua/wax/lib/stdlib/enums.lua +396 -0
  110. data/lib/candle/generators/lua/wax/lib/stdlib/ext/http.lua +43 -0
  111. data/lib/candle/generators/lua/wax/lib/stdlib/ext/init.lua +4 -0
  112. data/lib/candle/generators/lua/wax/lib/stdlib/ext/number.lua +21 -0
  113. data/lib/candle/generators/lua/wax/lib/stdlib/ext/string.lua +97 -0
  114. data/lib/candle/generators/lua/wax/lib/stdlib/ext/table.lua +165 -0
  115. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/WaxServer.lua +49 -0
  116. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/autoload.lua +10 -0
  117. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/base64.lua +64 -0
  118. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/bit.lua +274 -0
  119. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/cache.lua +73 -0
  120. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/callback.lua +22 -0
  121. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/frame.lua +76 -0
  122. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/init.lua +78 -0
  123. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/pickView.lua +54 -0
  124. data/lib/candle/generators/lua/wax/lib/stdlib/helpers/time.lua +102 -0
  125. data/lib/candle/generators/lua/wax/lib/stdlib/init.lua +18 -0
  126. data/lib/candle/generators/lua/wax/lib/stdlib/luaspec/init.lua +2 -0
  127. data/lib/candle/generators/lua/wax/lib/stdlib/luaspec/luamock.lua +84 -0
  128. data/lib/candle/generators/lua/wax/lib/stdlib/luaspec/luaspec.lua +377 -0
  129. data/lib/candle/generators/lua/wax/lib/stdlib/repl.lua +9 -0
  130. data/lib/candle/generators/lua/wax/lib/stdlib/structs.lua +11 -0
  131. data/lib/candle/generators/lua/wax/lib/stdlib/waxClass.lua +42 -0
  132. data/lib/candle/generators/lua/wax/lib/wax.h +16 -0
  133. data/lib/candle/generators/lua/wax/lib/wax.m +260 -0
  134. data/lib/candle/generators/lua/wax/lib/wax_class.h +18 -0
  135. data/lib/candle/generators/lua/wax/lib/wax_class.m +190 -0
  136. data/lib/candle/generators/lua/wax/lib/wax_gc.h +20 -0
  137. data/lib/candle/generators/lua/wax/lib/wax_gc.m +56 -0
  138. data/lib/candle/generators/lua/wax/lib/wax_helpers.h +102 -0
  139. data/lib/candle/generators/lua/wax/lib/wax_helpers.m +870 -0
  140. data/lib/candle/generators/lua/wax/lib/wax_instance.h +34 -0
  141. data/lib/candle/generators/lua/wax/lib/wax_instance.m +810 -0
  142. data/lib/candle/generators/lua/wax/lib/wax_server.h +47 -0
  143. data/lib/candle/generators/lua/wax/lib/wax_server.m +252 -0
  144. data/lib/candle/generators/lua/wax/lib/wax_stdlib.h +3 -0
  145. data/lib/candle/generators/lua/wax/lib/wax_struct.h +26 -0
  146. data/lib/candle/generators/lua/wax/lib/wax_struct.m +335 -0
  147. data/lib/candle/generators/templates/blank/WaxApplication.xcodeproj/project.pbxproj +836 -0
  148. data/lib/candle/generators/templates/blank/WaxApplication.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  149. data/lib/candle/generators/templates/blank/WaxApplication.xcodeproj/project.xcworkspace/xcuserdata/eiffel.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  150. data/lib/candle/generators/templates/blank/WaxApplication.xcodeproj/xcuserdata/eiffel.xcuserdatad/xcschemes/WaxApplication.xcscheme +86 -0
  151. data/lib/candle/generators/templates/blank/WaxApplication.xcodeproj/xcuserdata/eiffel.xcuserdatad/xcschemes/xcschememanagement.plist +22 -0
  152. data/lib/candle/generators/templates/blank/WaxApplication/Default-568h@2x.png +0 -0
  153. data/lib/candle/generators/templates/blank/WaxApplication/Default.png +0 -0
  154. data/lib/candle/generators/templates/blank/WaxApplication/Default@2x.png +0 -0
  155. data/lib/candle/generators/templates/blank/WaxApplication/ProtocolLoader.h +12 -0
  156. data/lib/candle/generators/templates/blank/WaxApplication/WaxApplication-Info.plist.tt +38 -0
  157. data/lib/candle/generators/templates/blank/WaxApplication/WaxApplication-Prefix.pch.tt +14 -0
  158. data/lib/candle/generators/templates/blank/WaxApplication/en.lproj/InfoPlist.strings +2 -0
  159. data/lib/candle/generators/templates/blank/WaxApplication/main.m.tt +20 -0
  160. data/lib/candle/tasks.rb +22 -0
  161. data/lib/candle/utility.rb +30 -0
  162. data/lib/candle/version.rb +9 -0
  163. data/lib/candle/view.rb +48 -0
  164. metadata +582 -0
@@ -0,0 +1,34 @@
1
+ /*
2
+ * wax_instance.h
3
+ * Lua
4
+ *
5
+ * Created by ProbablyInteractive on 5/18/09.
6
+ * Copyright 2009 Probably Interactive. All rights reserved.
7
+ *
8
+ */
9
+
10
+ #import <Foundation/Foundation.h>
11
+ #import <objc/runtime.h>
12
+ #import <objc/message.h>
13
+
14
+ #import "lua.h"
15
+
16
+ #define WAX_INSTANCE_METATABLE_NAME "wax.instance"
17
+
18
+ typedef struct _wax_instance_userdata {
19
+ id instance;
20
+ BOOL isClass;
21
+ Class isSuper; // isSuper not only stores whether the class is a super, but it also contains the value of the next superClass.
22
+ BOOL actAsSuper; // It only acts like a super once, when it is called for the first time.
23
+ } wax_instance_userdata;
24
+
25
+ int luaopen_wax_instance(lua_State *L);
26
+
27
+ wax_instance_userdata *wax_instance_create(lua_State *L, id instance, BOOL isClass);
28
+ wax_instance_userdata *wax_instance_createSuper(lua_State *L, wax_instance_userdata *instanceUserdata);
29
+ void wax_instance_pushUserdataTable(lua_State *L);
30
+ void wax_instance_pushStrongUserdataTable(lua_State *L);
31
+
32
+ BOOL wax_instance_pushFunction(lua_State *L, id self, SEL selector);
33
+ void wax_instance_pushUserdata(lua_State *L, id object);
34
+ BOOL wax_instance_isWaxClass(id instance);
@@ -0,0 +1,810 @@
1
+ /*
2
+ * wax_instance.c
3
+ * Lua
4
+ *
5
+ * Created by ProbablyInteractive on 5/18/09.
6
+ * Copyright 2009 Probably Interactive. All rights reserved.
7
+ *
8
+ */
9
+
10
+ #import "wax_instance.h"
11
+ #import "wax_class.h"
12
+ #import "wax.h"
13
+ #import "wax_helpers.h"
14
+
15
+ #import "lauxlib.h"
16
+ #import "lobject.h"
17
+
18
+ static int __index(lua_State *L);
19
+ static int __newindex(lua_State *L);
20
+ static int __gc(lua_State *L);
21
+ static int __tostring(lua_State *L);
22
+ static int __eq(lua_State *L);
23
+
24
+ static int methods(lua_State *L);
25
+
26
+ static int methodClosure(lua_State *L);
27
+ static int superMethodClosure(lua_State *L);
28
+ static int customInitMethodClosure(lua_State *L);
29
+
30
+ static BOOL overrideMethod(lua_State *L, wax_instance_userdata *instanceUserdata);
31
+ static int pcallUserdata(lua_State *L, id self, SEL selector, va_list args);
32
+
33
+ static const struct luaL_Reg metaFunctions[] = {
34
+ {"__index", __index},
35
+ {"__newindex", __newindex},
36
+ {"__gc", __gc},
37
+ {"__tostring", __tostring},
38
+ {"__eq", __eq},
39
+ {NULL, NULL}
40
+ };
41
+
42
+ static const struct luaL_Reg functions[] = {
43
+ {"methods", methods},
44
+ {NULL, NULL}
45
+ };
46
+
47
+ int luaopen_wax_instance(lua_State *L) {
48
+ BEGIN_STACK_MODIFY(L);
49
+
50
+ luaL_newmetatable(L, WAX_INSTANCE_METATABLE_NAME);
51
+ luaL_register(L, NULL, metaFunctions);
52
+ luaL_register(L, WAX_INSTANCE_METATABLE_NAME, functions);
53
+
54
+ END_STACK_MODIFY(L, 0)
55
+
56
+ return 1;
57
+ }
58
+
59
+ #pragma mark Instance Utils
60
+ #pragma mark -------------------
61
+
62
+ // Creates userdata object for obj-c instance/class and pushes it onto the stack
63
+ wax_instance_userdata *wax_instance_create(lua_State *L, id instance, BOOL isClass) {
64
+ BEGIN_STACK_MODIFY(L)
65
+
66
+ // Does user data already exist?
67
+ wax_instance_pushUserdata(L, instance);
68
+
69
+ if (lua_isnil(L, -1)) {
70
+ //wax_log(LOG_GC, @"Creating %@ for %@(%p)", isClass ? @"class" : @"instance", [instance class], instance);
71
+ lua_pop(L, 1); // pop nil stack
72
+ }
73
+ else {
74
+ //wax_log(LOG_GC, @"Found existing userdata %@ for %@(%p)", isClass ? @"class" : @"instance", [instance class], instance);
75
+ return lua_touserdata(L, -1);
76
+ }
77
+
78
+ size_t nbytes = sizeof(wax_instance_userdata);
79
+ wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)lua_newuserdata(L, nbytes);
80
+ instanceUserdata->instance = instance;
81
+ instanceUserdata->isClass = isClass;
82
+ instanceUserdata->isSuper = nil;
83
+ instanceUserdata->actAsSuper = NO;
84
+
85
+ if (!isClass) {
86
+ //wax_log(LOG_GC, @"Retaining %@ for %@(%p -> %p)", isClass ? @"class" : @"instance", [instance class], instance, instanceUserdata);
87
+ [instanceUserdata->instance retain];
88
+ }
89
+
90
+ // set the metatable
91
+ luaL_getmetatable(L, WAX_INSTANCE_METATABLE_NAME);
92
+ lua_setmetatable(L, -2);
93
+
94
+ // give it a nice clean environment
95
+ lua_newtable(L);
96
+ lua_setfenv(L, -2);
97
+
98
+ wax_instance_pushUserdataTable(L);
99
+
100
+ // register the userdata table in the metatable (so we can access it from obj-c)
101
+ //wax_log(LOG_GC, @"Storing reference of %@ to userdata table %@(%p -> %p)", isClass ? @"class" : @"instance", [instance class], instance, instanceUserdata);
102
+ lua_pushlightuserdata(L, instanceUserdata->instance);
103
+ lua_pushvalue(L, -3); // Push userdata
104
+ lua_rawset(L, -3);
105
+
106
+ lua_pop(L, 1); // Pop off userdata table
107
+
108
+
109
+ wax_instance_pushStrongUserdataTable(L);
110
+ lua_pushlightuserdata(L, instanceUserdata->instance);
111
+ lua_pushvalue(L, -3); // Push userdata
112
+ lua_rawset(L, -3);
113
+
114
+ //wax_log(LOG_GC, @"Storing reference to strong userdata table %@(%p -> %p)", [instance class], instance, instanceUserdata);
115
+
116
+ lua_pop(L, 1); // Pop off strong userdata table
117
+
118
+ END_STACK_MODIFY(L, 1)
119
+
120
+ return instanceUserdata;
121
+ }
122
+
123
+ // Creates pseudo-super userdata object for obj-c instance and pushes it onto the stack
124
+ wax_instance_userdata *wax_instance_createSuper(lua_State *L, wax_instance_userdata *instanceUserdata) {
125
+ BEGIN_STACK_MODIFY(L)
126
+
127
+ size_t nbytes = sizeof(wax_instance_userdata);
128
+ wax_instance_userdata *superInstanceUserdata = (wax_instance_userdata *)lua_newuserdata(L, nbytes);
129
+ superInstanceUserdata->instance = instanceUserdata->instance;
130
+ superInstanceUserdata->isClass = instanceUserdata->isClass;
131
+ superInstanceUserdata->actAsSuper = YES;
132
+
133
+ // isSuper not only stores whether the class is a super, but it also contains the value of the next superClass
134
+ if (instanceUserdata->isSuper) {
135
+ superInstanceUserdata->isSuper = [instanceUserdata->isSuper superclass];
136
+ }
137
+ else {
138
+ superInstanceUserdata->isSuper = [instanceUserdata->instance superclass];
139
+ }
140
+
141
+
142
+ // set the metatable
143
+ luaL_getmetatable(L, WAX_INSTANCE_METATABLE_NAME);
144
+ lua_setmetatable(L, -2);
145
+
146
+ wax_instance_pushUserdata(L, instanceUserdata->instance);
147
+ if (lua_isnil(L, -1)) { // instance has no lua object, push empty env table (This shouldn't happen, tempted to remove it)
148
+ lua_pop(L, 1); // Remove nil and superclass userdata
149
+ lua_newtable(L);
150
+ }
151
+ else {
152
+ lua_getfenv(L, -1);
153
+ lua_remove(L, -2); // Remove nil and superclass userdata
154
+ }
155
+
156
+ // Give it the instance's metatable
157
+ lua_setfenv(L, -2);
158
+
159
+ END_STACK_MODIFY(L, 1)
160
+
161
+ return superInstanceUserdata;
162
+ }
163
+
164
+ // The userdata table holds weak references too all the instance userdata
165
+ // created. This is used to manage all instances of Objective-C objects created
166
+ // via Lua so we can release/gc them when both Lua and Objective-C are finished with
167
+ // them.
168
+ void wax_instance_pushUserdataTable(lua_State *L) {
169
+ BEGIN_STACK_MODIFY(L)
170
+ static const char* userdataTableName = "__wax_userdata";
171
+ luaL_getmetatable(L, WAX_INSTANCE_METATABLE_NAME);
172
+ lua_getfield(L, -1, userdataTableName);
173
+
174
+ if (lua_isnil(L, -1)) { // Create new userdata table, add it to metatable
175
+ lua_pop(L, 1); // Remove nil
176
+
177
+ lua_pushstring(L, userdataTableName); // Table name
178
+ lua_newtable(L);
179
+ lua_rawset(L, -3); // Add userdataTableName table to WAX_INSTANCE_METATABLE_NAME
180
+ lua_getfield(L, -1, userdataTableName);
181
+
182
+ lua_pushvalue(L, -1);
183
+ lua_setmetatable(L, -2); // userdataTable is it's own metatable
184
+
185
+ lua_pushstring(L, "v");
186
+ lua_setfield(L, -2, "__mode"); // Make weak table
187
+ }
188
+
189
+ END_STACK_MODIFY(L, 1)
190
+ }
191
+
192
+ // Holds strong references to userdata created by wax... if the retain count dips below
193
+ // 2, then we can remove it because we know obj-c doesn't care about it anymore
194
+ void wax_instance_pushStrongUserdataTable(lua_State *L) {
195
+ BEGIN_STACK_MODIFY(L)
196
+ static const char* userdataTableName = "__wax_strong_userdata";
197
+ luaL_getmetatable(L, WAX_INSTANCE_METATABLE_NAME);
198
+ lua_getfield(L, -1, userdataTableName);
199
+
200
+ if (lua_isnil(L, -1)) { // Create new userdata table, add it to metatable
201
+ lua_pop(L, 1); // Remove nil
202
+
203
+ lua_pushstring(L, userdataTableName); // Table name
204
+ lua_newtable(L);
205
+ lua_rawset(L, -3); // Add userdataTableName table to WAX_INSTANCE_METATABLE_NAME
206
+ lua_getfield(L, -1, userdataTableName);
207
+ }
208
+
209
+ END_STACK_MODIFY(L, 1)
210
+ }
211
+
212
+
213
+ // First look in the object's userdata for the function, then look in the object's class's userdata
214
+ BOOL wax_instance_pushFunction(lua_State *L, id self, SEL selector) {
215
+ BEGIN_STACK_MODIFY(L)
216
+
217
+ wax_instance_pushUserdata(L, self);
218
+ if (lua_isnil(L, -1)) {
219
+ END_STACK_MODIFY(L, 0)
220
+ return NO; // userdata doesn't exist
221
+ }
222
+
223
+ lua_getfenv(L, -1);
224
+ wax_pushMethodNameFromSelector(L, selector);
225
+ lua_rawget(L, -2);
226
+
227
+ BOOL result = YES;
228
+
229
+ if (!lua_isfunction(L, -1)) { // function not found in userdata
230
+ lua_pop(L, 3); // Remove userdata, env and non-function
231
+ if ([self class] == self) { // This is a class, not an instance
232
+ result = wax_instance_pushFunction(L, [self superclass], selector); // Check to see if the super classes know about this function
233
+ }
234
+ else {
235
+ result = wax_instance_pushFunction(L, [self class], selector);
236
+ }
237
+ }
238
+
239
+ END_STACK_MODIFY(L, 1)
240
+
241
+ return result;
242
+ }
243
+
244
+ // Retrieves associated userdata for an object from the wax instance userdata table
245
+ void wax_instance_pushUserdata(lua_State *L, id object) {
246
+ BEGIN_STACK_MODIFY(L);
247
+
248
+ wax_instance_pushUserdataTable(L);
249
+ lua_pushlightuserdata(L, object);
250
+ lua_rawget(L, -2);
251
+ lua_remove(L, -2); // remove userdataTable
252
+
253
+
254
+ END_STACK_MODIFY(L, 1)
255
+ }
256
+
257
+ BOOL wax_instance_isWaxClass(id instance) {
258
+ // If this is a wax class, or an instance of a wax class, it has the userdata ivar set
259
+ return class_getInstanceVariable([instance class], WAX_CLASS_INSTANCE_USERDATA_IVAR_NAME) != nil;
260
+ }
261
+
262
+
263
+ #pragma mark Override Metatable Functions
264
+ #pragma mark ---------------------------------
265
+
266
+ static int __index(lua_State *L) {
267
+ wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
268
+
269
+ if (lua_isstring(L, 2) && strcmp("super", lua_tostring(L, 2)) == 0) { // call to super!
270
+ wax_instance_createSuper(L, instanceUserdata);
271
+ return 1;
272
+ }
273
+
274
+ // Check instance userdata, unless we are acting like a super
275
+ if (!instanceUserdata->actAsSuper) {
276
+ lua_getfenv(L, -2);
277
+ lua_pushvalue(L, -2);
278
+ lua_rawget(L, 3);
279
+ }
280
+ else {
281
+ lua_pushnil(L);
282
+ }
283
+
284
+ // Check instance's class userdata, or if it is a super, check the super's class data
285
+ Class classToCheck = instanceUserdata->actAsSuper ? instanceUserdata->isSuper : [instanceUserdata->instance class];
286
+ while (lua_isnil(L, -1) && wax_instance_isWaxClass(classToCheck)) {
287
+ // Keep checking superclasses if they are waxclasses, we want to treat those like they are lua
288
+ lua_pop(L, 1);
289
+ wax_instance_pushUserdata(L, classToCheck);
290
+
291
+ // If there is no userdata for this instance's class, then leave the nil on the stack and don't anything else
292
+ if (!lua_isnil(L, -1)) {
293
+ lua_getfenv(L, -1);
294
+ lua_pushvalue(L, 2);
295
+ lua_rawget(L, -2);
296
+ lua_remove(L, -2); // Get rid of the userdata env
297
+ lua_remove(L, -2); // Get rid of the userdata
298
+ }
299
+
300
+ classToCheck = class_getSuperclass(classToCheck);
301
+ }
302
+
303
+ if (lua_isnil(L, -1)) { // If we are calling a super class, or if we couldn't find the index in the userdata environment table, assume it is defined in obj-c classes
304
+ SEL foundSelectors[2] = {nil, nil};
305
+ BOOL foundSelector = wax_selectorForInstance(instanceUserdata, foundSelectors, lua_tostring(L, 2), NO);
306
+
307
+ if (foundSelector) { // If the class has a method with this name, push as a closure
308
+ lua_pushstring(L, sel_getName(foundSelectors[0]));
309
+ foundSelectors[1] ? lua_pushstring(L, sel_getName(foundSelectors[1])) : lua_pushnil(L);
310
+ lua_pushcclosure(L, instanceUserdata->actAsSuper ? superMethodClosure : methodClosure, 2);
311
+ }
312
+ }
313
+ else if (!instanceUserdata->isSuper && instanceUserdata->isClass && wax_isInitMethod(lua_tostring(L, 2))) { // Is this an init method create in lua?
314
+ lua_pushcclosure(L, customInitMethodClosure, 1);
315
+ }
316
+
317
+ // Always reset this, an object only acts like a super ONE TIME!
318
+ instanceUserdata->actAsSuper = NO;
319
+
320
+ return 1;
321
+ }
322
+
323
+ static int __newindex(lua_State *L) {
324
+ wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
325
+
326
+ // If this already exists in a protocol, or superclass make sure it will call the lua functions
327
+ if (instanceUserdata->isClass && lua_type(L, 3) == LUA_TFUNCTION) {
328
+ overrideMethod(L, instanceUserdata);
329
+ }
330
+
331
+ // Add value to the userdata's environment table
332
+ lua_getfenv(L, 1);
333
+ lua_insert(L, 2);
334
+ lua_rawset(L, 2);
335
+
336
+ return 0;
337
+ }
338
+
339
+ static int __gc(lua_State *L) {
340
+ wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
341
+
342
+ //wax_log(LOG_GC, @"Releasing %@ %@(%p)", instanceUserdata->isClass ? @"Class" : @"Instance", [instanceUserdata->instance class], instanceUserdata->instance);
343
+
344
+ if (!instanceUserdata->isClass && !instanceUserdata->isSuper) {
345
+ // This seems like a stupid hack. But...
346
+ // If we want to call methods on an object durring gc, we have to readd
347
+ // the instance/userdata to the userdata table. Why? Because it is
348
+ // removed from the weak table before GC is called.
349
+ wax_instance_pushUserdataTable(L);
350
+ lua_pushlightuserdata(L, instanceUserdata->instance);
351
+ lua_pushvalue(L, -3);
352
+ lua_rawset(L, -3);
353
+
354
+ [instanceUserdata->instance release];
355
+
356
+ lua_pushlightuserdata(L, instanceUserdata->instance);
357
+ lua_pushnil(L);
358
+ lua_rawset(L, -3);
359
+ lua_pop(L, 1);
360
+ }
361
+
362
+ return 0;
363
+ }
364
+
365
+ static int __tostring(lua_State *L) {
366
+ wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
367
+ lua_pushstring(L, [[NSString stringWithFormat:@"(%p => %p) %@", instanceUserdata, instanceUserdata->instance, instanceUserdata->instance] UTF8String]);
368
+
369
+ return 1;
370
+ }
371
+
372
+ static int __eq(lua_State *L) {
373
+ wax_instance_userdata *o1 = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
374
+ wax_instance_userdata *o2 = (wax_instance_userdata *)luaL_checkudata(L, 2, WAX_INSTANCE_METATABLE_NAME);
375
+
376
+ lua_pushboolean(L, [o1->instance isEqual:o2->instance]);
377
+ return 1;
378
+ }
379
+
380
+ #pragma mark Userdata Functions
381
+ #pragma mark -----------------------
382
+
383
+ static int methods(lua_State *L) {
384
+ wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
385
+
386
+ uint count;
387
+ Method *methods = class_copyMethodList([instanceUserdata->instance class], &count);
388
+
389
+ lua_newtable(L);
390
+
391
+ for (int i = 0; i < count; i++) {
392
+ Method method = methods[i];
393
+ lua_pushstring(L, sel_getName(method_getName(method)));
394
+ lua_rawseti(L, -2, i + 1);
395
+ }
396
+
397
+ return 1;
398
+ }
399
+
400
+ #pragma mark Function Closures
401
+ #pragma mark ----------------------
402
+
403
+ static int methodClosure(lua_State *L) {
404
+ if (![[NSThread currentThread] isEqual:[NSThread mainThread]]) NSLog(@"METHODCLOSURE: OH NO SEPERATE THREAD");
405
+
406
+ wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
407
+ const char *selectorName = luaL_checkstring(L, lua_upvalueindex(1));
408
+
409
+ // If the only arg is 'self' and there is a selector with no args. USE IT!
410
+ if (lua_gettop(L) == 1 && lua_isstring(L, lua_upvalueindex(2))) {
411
+ selectorName = luaL_checkstring(L, lua_upvalueindex(2));
412
+ }
413
+
414
+ SEL selector = sel_getUid(selectorName);
415
+ id instance = instanceUserdata->instance;
416
+ BOOL autoAlloc = NO;
417
+
418
+ // If init is called on a class, auto-allocate it.
419
+ if (instanceUserdata->isClass && wax_isInitMethod(selectorName)) {
420
+ autoAlloc = YES;
421
+ instance = [instance alloc];
422
+ }
423
+
424
+ NSMethodSignature *signature = [instance methodSignatureForSelector:selector];
425
+ if (!signature) {
426
+ const char *className = [NSStringFromClass([instance class]) UTF8String];
427
+ luaL_error(L, "'%s' has no method selector '%s'", className, selectorName);
428
+ }
429
+
430
+ NSInvocation *invocation = nil;
431
+ invocation = [NSInvocation invocationWithMethodSignature:signature];
432
+
433
+ [invocation setTarget:instance];
434
+ [invocation setSelector:selector];
435
+
436
+ int objcArgumentCount = [signature numberOfArguments] - 2; // skip the hidden self and _cmd argument
437
+ int luaArgumentCount = lua_gettop(L) - 1;
438
+
439
+
440
+ if (objcArgumentCount > luaArgumentCount && !wax_instance_isWaxClass(instance)) {
441
+ luaL_error(L, "Not Enough arguments given! Method named '%s' requires %d argument(s), you gave %d. (Make sure you used ':' to call the method)", selectorName, objcArgumentCount + 1, lua_gettop(L));
442
+ }
443
+
444
+ void **arguements = calloc(sizeof(void*), objcArgumentCount);
445
+ for (int i = 0; i < objcArgumentCount; i++) {
446
+ arguements[i] = wax_copyToObjc(L, [signature getArgumentTypeAtIndex:i + 2], i + 2, nil);
447
+ [invocation setArgument:arguements[i] atIndex:i + 2];
448
+ }
449
+
450
+ @try {
451
+ [invocation invoke];
452
+ }
453
+ @catch (NSException *exception) {
454
+ luaL_error(L, "Error invoking method '%s' on '%s' because %s", selector, class_getName([instance class]), [[exception description] UTF8String]);
455
+ }
456
+
457
+ for (int i = 0; i < objcArgumentCount; i++) {
458
+ free(arguements[i]);
459
+ }
460
+ free(arguements);
461
+
462
+ int methodReturnLength = [signature methodReturnLength];
463
+ if (methodReturnLength > 0) {
464
+ void *buffer = calloc(1, methodReturnLength);
465
+ [invocation getReturnValue:buffer];
466
+
467
+ wax_fromObjc(L, [signature methodReturnType], buffer);
468
+
469
+ if (autoAlloc) {
470
+ if (lua_isnil(L, -1)) {
471
+ // The init method returned nil... means initialization failed!
472
+ // Remove it from the userdataTable (We don't ever want to clean up after this... it should have cleaned up after itself)
473
+ wax_instance_pushUserdataTable(L);
474
+ lua_pushlightuserdata(L, instance);
475
+ lua_pushnil(L);
476
+ lua_rawset(L, -3);
477
+ lua_pop(L, 1); // Pop the userdataTable
478
+
479
+ lua_pushnil(L);
480
+ [instance release];
481
+ }
482
+ else {
483
+ wax_instance_userdata *returnedInstanceUserdata = (wax_instance_userdata *)lua_topointer(L, -1);
484
+ if (returnedInstanceUserdata) { // Could return nil
485
+ [returnedInstanceUserdata->instance release]; // Wax automatically retains a copy of the object, so the alloc needs to be released
486
+ }
487
+ }
488
+ }
489
+
490
+ free(buffer);
491
+ }
492
+
493
+ return 1;
494
+ }
495
+
496
+ static int superMethodClosure(lua_State *L) {
497
+ wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
498
+ const char *selectorName = luaL_checkstring(L, lua_upvalueindex(1));
499
+
500
+ // If the only arg is 'self' and there is a selector with no args. USE IT!
501
+ if (lua_gettop(L) == 1 && lua_isstring(L, lua_upvalueindex(2))) {
502
+ selectorName = luaL_checkstring(L, lua_upvalueindex(2));
503
+ }
504
+
505
+ SEL selector = sel_getUid(selectorName);
506
+
507
+ // Super Swizzle
508
+ Method selfMethod = class_getInstanceMethod([instanceUserdata->instance class], selector);
509
+ Method superMethod = class_getInstanceMethod(instanceUserdata->isSuper, selector);
510
+
511
+ if (superMethod && selfMethod != superMethod) { // Super's got what you're looking for
512
+ IMP selfMethodImp = method_getImplementation(selfMethod);
513
+ IMP superMethodImp = method_getImplementation(superMethod);
514
+ method_setImplementation(selfMethod, superMethodImp);
515
+
516
+ methodClosure(L);
517
+
518
+ method_setImplementation(selfMethod, selfMethodImp); // Swap back to self's original method
519
+ }
520
+ else {
521
+ methodClosure(L);
522
+ }
523
+
524
+ return 1;
525
+ }
526
+
527
+ static int customInitMethodClosure(lua_State *L) {
528
+ wax_instance_userdata *classInstanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
529
+ wax_instance_userdata *instanceUserdata = nil;
530
+
531
+ id instance = nil;
532
+ BOOL shouldRelease = NO;
533
+ if (classInstanceUserdata->isClass) {
534
+ shouldRelease = YES;
535
+ instance = [classInstanceUserdata->instance alloc];
536
+ instanceUserdata = wax_instance_create(L, instance, NO);
537
+ lua_replace(L, 1); // replace the old userdata with the new one!
538
+ }
539
+ else {
540
+ luaL_error(L, "I WAS TOLD THIS WAS A CUSTOM INIT METHOD. BUT YOU LIED TO ME");
541
+ return -1;
542
+ }
543
+
544
+ lua_pushvalue(L, lua_upvalueindex(1)); // Grab the function!
545
+ lua_insert(L, 1); // push it up top
546
+
547
+ if (wax_pcall(L, lua_gettop(L) - 1, 1)) {
548
+ const char* errorString = lua_tostring(L, -1);
549
+ luaL_error(L, "Custom init method on '%s' failed.\n%s", class_getName([instanceUserdata->instance class]), errorString);
550
+ }
551
+
552
+ if (shouldRelease) {
553
+ [instance release];
554
+ }
555
+
556
+ if (lua_isnil(L, -1)) { // The init method returned nil... return the instanceUserdata instead
557
+ luaL_error(L, "Init method must return the self");
558
+ }
559
+
560
+ return 1;
561
+ }
562
+
563
+ #pragma mark Override Methods
564
+ #pragma mark ---------------------
565
+
566
+ static int pcallUserdata(lua_State *L, id self, SEL selector, va_list args) {
567
+ BEGIN_STACK_MODIFY(L)
568
+
569
+ if (![[NSThread currentThread] isEqual:[NSThread mainThread]]) NSLog(@"PCALLUSERDATA: OH NO SEPERATE THREAD");
570
+
571
+ // A WaxClass could have been created via objective-c (like via NSKeyUnarchiver)
572
+ // In this case, no lua object was ever associated with it, so we've got to
573
+ // create one.
574
+ if (wax_instance_isWaxClass(self)) {
575
+ BOOL isClass = self == [self class];
576
+ wax_instance_create(L, self, isClass); // If it already exists, then it will just return without doing anything
577
+ lua_pop(L, 1); // Pops userdata off
578
+ }
579
+
580
+ // Find the function... could be in the object or in the class
581
+ if (!wax_instance_pushFunction(L, self, selector)) {
582
+ lua_pushfstring(L, "Could not find function named \"%s\" associated with object %s(%p).(It may have been released by the GC)", selector, class_getName([self class]), self);
583
+ goto error; // function not found in userdata...
584
+ }
585
+
586
+ // Push userdata as the first argument
587
+ wax_fromInstance(L, self);
588
+ if (lua_isnil(L, -1)) {
589
+ lua_pushfstring(L, "Could not convert '%s' into lua", class_getName([self class]));
590
+ goto error;
591
+ }
592
+
593
+ NSMethodSignature *signature = [self methodSignatureForSelector:selector];
594
+ int nargs = [signature numberOfArguments] - 1; // Don't send in the _cmd argument, only self
595
+ int nresults = [signature methodReturnLength] ? 1 : 0;
596
+
597
+ for (int i = 2; i < [signature numberOfArguments]; i++) { // start at 2 because to skip the automatic self and _cmd arugments
598
+ const char *type = [signature getArgumentTypeAtIndex:i];
599
+ int size = wax_fromObjc(L, type, args);
600
+ args += size; // HACK! Since va_arg requires static type, I manually increment the args
601
+ }
602
+
603
+ if (wax_pcall(L, nargs, nresults)) { // Userdata will allways be the first object sent to the function
604
+ goto error;
605
+ }
606
+
607
+ END_STACK_MODIFY(L, nresults)
608
+ return nresults;
609
+
610
+ error:
611
+ END_STACK_MODIFY(L, 1)
612
+ return -1;
613
+ }
614
+
615
+ #define WAX_METHOD_NAME(_type_) wax_##_type_##_call
616
+
617
+ #define WAX_METHOD(_type_) \
618
+ static _type_ WAX_METHOD_NAME(_type_)(id self, SEL _cmd, ...) { \
619
+ va_list args; \
620
+ va_start(args, _cmd); \
621
+ va_list args_copy; \
622
+ va_copy(args_copy, args); \
623
+ /* Grab the static L... this is a hack */ \
624
+ lua_State *L = wax_currentLuaState(); \
625
+ BEGIN_STACK_MODIFY(L); \
626
+ int result = pcallUserdata(L, self, _cmd, args_copy); \
627
+ va_end(args_copy); \
628
+ va_end(args); \
629
+ if (result == -1) { \
630
+ luaL_error(L, "Error calling '%s' on '%s'\n%s", _cmd, [[self description] UTF8String], lua_tostring(L, -1)); \
631
+ } \
632
+ else if (result == 0) { \
633
+ _type_ returnValue; \
634
+ bzero(&returnValue, sizeof(_type_)); \
635
+ END_STACK_MODIFY(L, 0) \
636
+ return returnValue; \
637
+ } \
638
+ \
639
+ NSMethodSignature *signature = [self methodSignatureForSelector:_cmd]; \
640
+ _type_ *pReturnValue = (_type_ *)wax_copyToObjc(L, [signature methodReturnType], -1, nil); \
641
+ _type_ returnValue = *pReturnValue; \
642
+ free(pReturnValue); \
643
+ END_STACK_MODIFY(L, 0) \
644
+ return returnValue; \
645
+ }
646
+
647
+ typedef struct _buffer_16 {char b[16];} buffer_16;
648
+
649
+ WAX_METHOD(buffer_16)
650
+ WAX_METHOD(id)
651
+ WAX_METHOD(int)
652
+ WAX_METHOD(long)
653
+ WAX_METHOD(float)
654
+ WAX_METHOD(BOOL)
655
+
656
+ // Only allow classes to do this
657
+ static BOOL overrideMethod(lua_State *L, wax_instance_userdata *instanceUserdata) {
658
+ BEGIN_STACK_MODIFY(L);
659
+ BOOL success = NO;
660
+ const char *methodName = lua_tostring(L, 2);
661
+
662
+ SEL foundSelectors[2] = {nil, nil};
663
+ wax_selectorForInstance(instanceUserdata, foundSelectors, methodName, YES);
664
+ SEL selector = foundSelectors[0];
665
+ if (foundSelectors[1]) {
666
+ //NSLog(@"Found two selectors that match %s. Defaulting to %s over %s", methodName, foundSelectors[0], foundSelectors[1]);
667
+ }
668
+
669
+ Class klass = [instanceUserdata->instance class];
670
+
671
+ char *typeDescription = nil;
672
+ char *returnType = nil;
673
+
674
+ Method method = class_getInstanceMethod(klass, selector);
675
+
676
+ if (method) { // Is method defined in the superclass?
677
+ typeDescription = (char *)method_getTypeEncoding(method);
678
+ returnType = method_copyReturnType(method);
679
+ }
680
+ else { // Is this method implementing a protocol?
681
+ Class currentClass = klass;
682
+
683
+ while (!returnType && [currentClass superclass] != [currentClass class]) { // Walk up the object heirarchy
684
+ uint count;
685
+ Protocol **protocols = class_copyProtocolList(currentClass, &count);
686
+
687
+ SEL possibleSelectors[2];
688
+ wax_selectorsForName(methodName, possibleSelectors);
689
+
690
+ for (int i = 0; !returnType && i < count; i++) {
691
+ Protocol *protocol = protocols[i];
692
+ struct objc_method_description m_description;
693
+
694
+ for (int j = 0; !returnType && j < 2; j++) {
695
+ selector = possibleSelectors[j];
696
+ if (!selector) continue; // There may be only one acceptable selector sent back
697
+
698
+ m_description = protocol_getMethodDescription(protocol, selector, YES, YES);
699
+ if (!m_description.name) m_description = protocol_getMethodDescription(protocol, selector, NO, YES); // Check if it is not a "required" method
700
+
701
+ if (m_description.name) {
702
+ typeDescription = m_description.types;
703
+ returnType = method_copyReturnType((Method)&m_description);
704
+ }
705
+ }
706
+ }
707
+
708
+ free(protocols);
709
+
710
+ currentClass = [currentClass superclass];
711
+ }
712
+ }
713
+
714
+ if (returnType) { // Matching method found! Create an Obj-C method on the
715
+ if (!instanceUserdata->isClass) {
716
+ luaL_error(L, "Trying to override method '%s' on an instance. You can only override classes", methodName);
717
+ }
718
+
719
+ const char *simplifiedReturnType = wax_removeProtocolEncodings(returnType);
720
+ IMP imp;
721
+ switch (simplifiedReturnType[0]) {
722
+ case WAX_TYPE_VOID:
723
+ case WAX_TYPE_ID:
724
+ imp = (IMP)WAX_METHOD_NAME(id);
725
+ break;
726
+
727
+ case WAX_TYPE_CHAR:
728
+ case WAX_TYPE_INT:
729
+ case WAX_TYPE_SHORT:
730
+ case WAX_TYPE_UNSIGNED_CHAR:
731
+ case WAX_TYPE_UNSIGNED_INT:
732
+ case WAX_TYPE_UNSIGNED_SHORT:
733
+ imp = (IMP)WAX_METHOD_NAME(int);
734
+ break;
735
+
736
+ case WAX_TYPE_LONG:
737
+ case WAX_TYPE_LONG_LONG:
738
+ case WAX_TYPE_UNSIGNED_LONG:
739
+ case WAX_TYPE_UNSIGNED_LONG_LONG:
740
+ imp = (IMP)WAX_METHOD_NAME(long);
741
+ break;
742
+
743
+ case WAX_TYPE_FLOAT:
744
+ imp = (IMP)WAX_METHOD_NAME(float);
745
+ break;
746
+
747
+ case WAX_TYPE_C99_BOOL:
748
+ imp = (IMP)WAX_METHOD_NAME(BOOL);
749
+ break;
750
+
751
+ case WAX_TYPE_STRUCT: {
752
+ int size = wax_sizeOfTypeDescription(simplifiedReturnType);
753
+ switch (size) {
754
+ case 16:
755
+ imp = (IMP)WAX_METHOD_NAME(buffer_16);
756
+ break;
757
+ default:
758
+ luaL_error(L, "Trying to override a method that has a struct return type of size '%d'. There is no implementation for this size yet.", size);
759
+ return NO;
760
+ break;
761
+ }
762
+ break;
763
+ }
764
+
765
+ default:
766
+ luaL_error(L, "Can't override method with return type %s", simplifiedReturnType);
767
+ return NO;
768
+ break;
769
+ }
770
+
771
+ id metaclass = objc_getMetaClass(object_getClassName(klass));
772
+ success = class_addMethod(klass, selector, imp, typeDescription) && class_addMethod(metaclass, selector, imp, typeDescription);
773
+
774
+ if (returnType) free(returnType);
775
+ }
776
+ else {
777
+ SEL possibleSelectors[2];
778
+ wax_selectorsForName(methodName, possibleSelectors);
779
+
780
+ success = YES;
781
+ for (int i = 0; i < 2; i++) {
782
+ selector = possibleSelectors[i];
783
+ if (!selector) continue; // There may be only one acceptable selector sent back
784
+
785
+ int argCount = 0;
786
+ char *match = (char *)sel_getName(selector);
787
+ while ((match = strchr(match, ':'))) {
788
+ match += 1; // Skip past the matched char
789
+ argCount++;
790
+ }
791
+
792
+ size_t typeDescriptionSize = 3 + argCount;
793
+ typeDescription = calloc(typeDescriptionSize + 1, sizeof(char));
794
+ memset(typeDescription, '@', typeDescriptionSize);
795
+ typeDescription[2] = ':'; // Never forget _cmd!
796
+
797
+ IMP imp = (IMP)WAX_METHOD_NAME(id);
798
+ id metaclass = objc_getMetaClass(object_getClassName(klass));
799
+
800
+ success = success &&
801
+ class_addMethod(klass, possibleSelectors[i], imp, typeDescription) &&
802
+ class_addMethod(metaclass, possibleSelectors[i], imp, typeDescription);
803
+
804
+ free(typeDescription);
805
+ }
806
+ }
807
+
808
+ END_STACK_MODIFY(L, 1)
809
+ return success;
810
+ }