candle 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }