dub 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/.gitignore +8 -0
  2. data/History.txt +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +53 -0
  5. data/Rakefile +58 -0
  6. data/dub.gemspec +194 -0
  7. data/lib/dub/argument.rb +261 -0
  8. data/lib/dub/entities_unescape.rb +16 -0
  9. data/lib/dub/function.rb +111 -0
  10. data/lib/dub/function_group.rb +74 -0
  11. data/lib/dub/generator.rb +15 -0
  12. data/lib/dub/group.rb +10 -0
  13. data/lib/dub/klass.rb +231 -0
  14. data/lib/dub/lua/class.cpp.erb +75 -0
  15. data/lib/dub/lua/class_gen.rb +78 -0
  16. data/lib/dub/lua/function.cpp.erb +4 -0
  17. data/lib/dub/lua/function_gen.rb +223 -0
  18. data/lib/dub/lua/group.cpp.erb +10 -0
  19. data/lib/dub/lua/lua_cpp_helper.h +141 -0
  20. data/lib/dub/lua/namespace.cpp.erb +35 -0
  21. data/lib/dub/lua/namespace_gen.rb +86 -0
  22. data/lib/dub/lua.rb +24 -0
  23. data/lib/dub/member_extraction.rb +88 -0
  24. data/lib/dub/namespace.rb +276 -0
  25. data/lib/dub/parser.rb +46 -0
  26. data/lib/dub/templates/lua_template.erb +21 -0
  27. data/lib/dub/version.rb +3 -0
  28. data/lib/dub.rb +26 -0
  29. data/test/argument_test.rb +423 -0
  30. data/test/fixtures/app/CMakeLists.txt +54 -0
  31. data/test/fixtures/app/Doxyfile +1600 -0
  32. data/test/fixtures/app/bindings/all_lua.cpp +299 -0
  33. data/test/fixtures/app/include/matrix.h +123 -0
  34. data/test/fixtures/app/make_lua_bindings.rb +13 -0
  35. data/test/fixtures/app/vendor/lua/CMakeLists.txt +25 -0
  36. data/test/fixtures/app/vendor/lua/COPYRIGHT +34 -0
  37. data/test/fixtures/app/vendor/lua/HISTORY +183 -0
  38. data/test/fixtures/app/vendor/lua/INSTALL +99 -0
  39. data/test/fixtures/app/vendor/lua/Makefile +183 -0
  40. data/test/fixtures/app/vendor/lua/README +37 -0
  41. data/test/fixtures/app/vendor/lua/lapi.c +1080 -0
  42. data/test/fixtures/app/vendor/lua/lapi.h +16 -0
  43. data/test/fixtures/app/vendor/lua/lauxlib.c +653 -0
  44. data/test/fixtures/app/vendor/lua/lauxlib.h +174 -0
  45. data/test/fixtures/app/vendor/lua/lbaselib.c +643 -0
  46. data/test/fixtures/app/vendor/lua/lcode.c +839 -0
  47. data/test/fixtures/app/vendor/lua/lcode.h +76 -0
  48. data/test/fixtures/app/vendor/lua/ldblib.c +397 -0
  49. data/test/fixtures/app/vendor/lua/ldebug.c +622 -0
  50. data/test/fixtures/app/vendor/lua/ldebug.h +33 -0
  51. data/test/fixtures/app/vendor/lua/ldo.c +516 -0
  52. data/test/fixtures/app/vendor/lua/ldo.h +57 -0
  53. data/test/fixtures/app/vendor/lua/ldump.c +164 -0
  54. data/test/fixtures/app/vendor/lua/lfunc.c +174 -0
  55. data/test/fixtures/app/vendor/lua/lfunc.h +34 -0
  56. data/test/fixtures/app/vendor/lua/lgc.c +711 -0
  57. data/test/fixtures/app/vendor/lua/lgc.h +110 -0
  58. data/test/fixtures/app/vendor/lua/liblua.a +0 -0
  59. data/test/fixtures/app/vendor/lua/linit.c +38 -0
  60. data/test/fixtures/app/vendor/lua/liolib.c +532 -0
  61. data/test/fixtures/app/vendor/lua/llex.c +461 -0
  62. data/test/fixtures/app/vendor/lua/llex.h +81 -0
  63. data/test/fixtures/app/vendor/lua/llimits.h +128 -0
  64. data/test/fixtures/app/vendor/lua/lmathlib.c +263 -0
  65. data/test/fixtures/app/vendor/lua/lmem.c +86 -0
  66. data/test/fixtures/app/vendor/lua/lmem.h +49 -0
  67. data/test/fixtures/app/vendor/lua/loadlib.c +664 -0
  68. data/test/fixtures/app/vendor/lua/lobject.c +214 -0
  69. data/test/fixtures/app/vendor/lua/lobject.h +381 -0
  70. data/test/fixtures/app/vendor/lua/lopcodes.c +102 -0
  71. data/test/fixtures/app/vendor/lua/lopcodes.h +268 -0
  72. data/test/fixtures/app/vendor/lua/loslib.c +244 -0
  73. data/test/fixtures/app/vendor/lua/lparser.c +1337 -0
  74. data/test/fixtures/app/vendor/lua/lparser.h +82 -0
  75. data/test/fixtures/app/vendor/lua/lstate.c +214 -0
  76. data/test/fixtures/app/vendor/lua/lstate.h +168 -0
  77. data/test/fixtures/app/vendor/lua/lstring.c +111 -0
  78. data/test/fixtures/app/vendor/lua/lstring.h +31 -0
  79. data/test/fixtures/app/vendor/lua/lstrlib.c +868 -0
  80. data/test/fixtures/app/vendor/lua/ltable.c +588 -0
  81. data/test/fixtures/app/vendor/lua/ltable.h +40 -0
  82. data/test/fixtures/app/vendor/lua/ltablib.c +278 -0
  83. data/test/fixtures/app/vendor/lua/ltm.c +75 -0
  84. data/test/fixtures/app/vendor/lua/ltm.h +54 -0
  85. data/test/fixtures/app/vendor/lua/lua.c +695 -0
  86. data/test/fixtures/app/vendor/lua/lua.h +385 -0
  87. data/test/fixtures/app/vendor/lua/lua_dub_helper.h +77 -0
  88. data/test/fixtures/app/vendor/lua/luac +0 -0
  89. data/test/fixtures/app/vendor/lua/luac.c +200 -0
  90. data/test/fixtures/app/vendor/lua/luaconf.h +762 -0
  91. data/test/fixtures/app/vendor/lua/lualib.h +53 -0
  92. data/test/fixtures/app/vendor/lua/lundump.c +223 -0
  93. data/test/fixtures/app/vendor/lua/lundump.h +36 -0
  94. data/test/fixtures/app/vendor/lua/lvm.c +765 -0
  95. data/test/fixtures/app/vendor/lua/lvm.h +36 -0
  96. data/test/fixtures/app/vendor/lua/lzio.c +82 -0
  97. data/test/fixtures/app/vendor/lua/lzio.h +67 -0
  98. data/test/fixtures/app/vendor/lua/matrix.h +102 -0
  99. data/test/fixtures/app/vendor/lua/print.c +227 -0
  100. data/test/fixtures/app/vendor/lua/test/README +26 -0
  101. data/test/fixtures/app/vendor/lua/test/bisect.lua +27 -0
  102. data/test/fixtures/app/vendor/lua/test/cf.lua +16 -0
  103. data/test/fixtures/app/vendor/lua/test/echo.lua +5 -0
  104. data/test/fixtures/app/vendor/lua/test/env.lua +7 -0
  105. data/test/fixtures/app/vendor/lua/test/factorial.lua +32 -0
  106. data/test/fixtures/app/vendor/lua/test/fib.lua +40 -0
  107. data/test/fixtures/app/vendor/lua/test/fibfor.lua +13 -0
  108. data/test/fixtures/app/vendor/lua/test/globals.lua +13 -0
  109. data/test/fixtures/app/vendor/lua/test/hello.lua +3 -0
  110. data/test/fixtures/app/vendor/lua/test/life.lua +111 -0
  111. data/test/fixtures/app/vendor/lua/test/luac.lua +7 -0
  112. data/test/fixtures/app/vendor/lua/test/printf.lua +7 -0
  113. data/test/fixtures/app/vendor/lua/test/readonly.lua +12 -0
  114. data/test/fixtures/app/vendor/lua/test/sieve.lua +29 -0
  115. data/test/fixtures/app/vendor/lua/test/sort.lua +66 -0
  116. data/test/fixtures/app/vendor/lua/test/table.lua +12 -0
  117. data/test/fixtures/app/vendor/lua/test/trace-calls.lua +32 -0
  118. data/test/fixtures/app/vendor/lua/test/trace-globals.lua +38 -0
  119. data/test/fixtures/app/vendor/lua/test/xd.lua +14 -0
  120. data/test/fixtures/app/xml/classdub_1_1_matrix.xml +239 -0
  121. data/test/fixtures/app/xml/classdub_1_1_t_mat.xml +233 -0
  122. data/test/fixtures/app/xml/combine.xslt +15 -0
  123. data/test/fixtures/app/xml/compound.xsd +814 -0
  124. data/test/fixtures/app/xml/dir_53661a2bdeb1d55e60581a7e15deb763.xml +12 -0
  125. data/test/fixtures/app/xml/index.xml +42 -0
  126. data/test/fixtures/app/xml/index.xsd +66 -0
  127. data/test/fixtures/app/xml/matrix_8h.xml +149 -0
  128. data/test/fixtures/app/xml/namespacedub.xml +41 -0
  129. data/test/fixtures/classcv_1_1_mat.xml +1996 -0
  130. data/test/fixtures/classcv_1_1_point__.xml +341 -0
  131. data/test/fixtures/classcv_1_1_size__.xml +270 -0
  132. data/test/fixtures/group___magic_type.xml +406 -0
  133. data/test/fixtures/namespacecv.xml +12659 -0
  134. data/test/function_group_test.rb +15 -0
  135. data/test/function_test.rb +252 -0
  136. data/test/group_test.rb +155 -0
  137. data/test/helper.rb +34 -0
  138. data/test/klass_test.rb +297 -0
  139. data/test/lua_function_gen_test.rb +179 -0
  140. data/test/namespace_test.rb +220 -0
  141. data/test/parser_test.rb +36 -0
  142. metadata +216 -0
@@ -0,0 +1,223 @@
1
+ require 'dub/generator'
2
+ require 'erb'
3
+
4
+ module Dub
5
+ module Lua
6
+ class FunctionGen < Dub::Generator
7
+ FLOAT_TYPES = [
8
+ 'float',
9
+ 'double',
10
+ 'size_t',
11
+ 'unsigned int',
12
+ 'uint',
13
+ ]
14
+
15
+ INT_TYPES = [
16
+ 'int',
17
+ 'size_t',
18
+ 'unsigned int',
19
+ 'uint',
20
+ 'bool',
21
+ 'uchar'
22
+ ]
23
+
24
+ def initialize
25
+ @function_template = ::ERB.new(File.read(File.join(File.dirname(__FILE__), 'function.cpp.erb')))
26
+ @group_template = ::ERB.new(File.read(File.join(File.dirname(__FILE__), 'group.cpp.erb')))
27
+ end
28
+
29
+ # Produce bindings for a group of overloaded functions
30
+ def group(group)
31
+ @group = group
32
+ @group_template.result(binding)
33
+ end
34
+
35
+ def function(function)
36
+ @function = function
37
+ @function_template.result(binding)
38
+ end
39
+
40
+ def function_generator
41
+ self
42
+ end
43
+
44
+ def namespace_generator
45
+ Dub::Lua.namespace_generator
46
+ end
47
+
48
+ # Create a switch to choose the correct method from argument types (overloaded functions)
49
+ def switch(hash_or_function, depth = 1)
50
+ if hash_or_function.kind_of?(Function)
51
+ method_call(hash_or_function)
52
+ else
53
+ res = []
54
+ res << "type__ = lua_type(L, #{depth});" unless depth == 1
55
+ else_prefix = ''
56
+ default_sub_group = nil
57
+ hash_or_function.each do |type, sub_group|
58
+ default_sub_group = sub_group
59
+ case type
60
+ when :number
61
+ res << "#{else_prefix}if (type__ == LUA_TNUMBER) {"
62
+ when :string
63
+ res << "#{else_prefix}if (type__ == LUA_TSTRING) {"
64
+ when nil
65
+ res << "#{else_prefix}if (type__ == LUA_TNONE) {"
66
+ else
67
+ res << "#{else_prefix}if (type__ == LUA_TUSERDATA && is_userdata(L, #{depth}, \"#{type}\")) {"
68
+ end
69
+
70
+ res << indent(switch(sub_group, depth + 1), 2)
71
+
72
+ else_prefix = '} else '
73
+ end
74
+
75
+ last = default_sub_group.kind_of?(Hash) ? flatten_hash(default_sub_group).last : default_sub_group
76
+
77
+ res << "} else {"
78
+ res << " // use any to raise errors"
79
+ res << indent(method_call(last), 2)
80
+ res << "}"
81
+ res.join("\n")
82
+ end
83
+ end
84
+
85
+ def signature(func, overloaded_index = nil)
86
+ "static int #{method_name(func, overloaded_index)}(lua_State *L)"
87
+ end
88
+
89
+ def body(func)
90
+ res = []
91
+
92
+ if func.member_method? && !func.constructor?
93
+ klass = func.parent
94
+ res << "#{klass.name} *self__ = *((#{klass.name}**)luaL_checkudata(L, 1, #{klass.id_name.inspect}));"
95
+ res << "lua_remove(L, 1);"
96
+ end
97
+
98
+ if func.has_default_arguments?
99
+ res << "int top__ = lua_gettop(L);"
100
+ if return_value = func.return_value
101
+ res << "#{return_value.create_type} retval__;"
102
+ end
103
+ end
104
+
105
+ if_indent = 0
106
+ func.arguments.each_with_index do |arg, i|
107
+ if arg.has_default?
108
+ res << indent("if (top__ < #{i+1}) {", if_indent)
109
+ res << indent(" #{call_string(func, i)}", if_indent)
110
+ res << indent("} else {", if_indent)
111
+ if_indent += 2
112
+ end
113
+ res << indent(get_arg(arg, i + 1), if_indent)
114
+ end
115
+ res << indent(call_string(func, func.arguments.count), if_indent)
116
+ while if_indent > 0
117
+ if_indent -= 2
118
+ res << indent("}", if_indent)
119
+ end
120
+
121
+ res << return_value(func)
122
+ res.join("\n")
123
+ end
124
+
125
+ def method_name(func, overloaded_index = nil)
126
+ overloaded_index ||= func.overloaded_index
127
+ overloaded_index = '' if overloaded_index == 0
128
+ "#{func.prefix}_#{func.name}#{overloaded_index}"
129
+ end
130
+
131
+ def method_call(func)
132
+ "return #{method_name(func)}(L);"
133
+ end
134
+
135
+ def call_string(func, upto_arg)
136
+ if upto_arg == 0
137
+ call_string = "#{func.name}();"
138
+ else
139
+ call_string = "#{func.name}(#{func.arguments[0..(upto_arg-1)].map{|arg| arg.in_call_type}.join(', ')});"
140
+ end
141
+
142
+ if func.constructor?
143
+ call_string = "new #{call_string}"
144
+ elsif func.member_method?
145
+ call_string = "self__->#{call_string}"
146
+ end
147
+
148
+
149
+ if return_value = func.return_value
150
+ if func.has_default_arguments?
151
+ "retval__ = #{call_string}"
152
+ else
153
+ "#{return_value.create_type} retval__ = #{call_string}"
154
+ end
155
+ else
156
+ call_string
157
+ end
158
+ end
159
+
160
+ def return_value(func)
161
+ res = []
162
+ if return_value = func.return_value
163
+ case Argument.type_group(return_value)
164
+ when :number
165
+ res << "lua_pushnumber(L, retval__);"
166
+ when :string
167
+ raise "Not supported yet"
168
+ else
169
+ if func.constructor?
170
+ prefix = func.klass.prefix
171
+ else
172
+ prefix = func.prefix
173
+ end
174
+ res << "lua_pushclass<#{return_value.type}>(L, retval__, \"#{return_value.id_name}\");"
175
+ end
176
+ res << "return 1;"
177
+ else
178
+ res << "return 0;"
179
+ end
180
+ res.join("\n")
181
+ end
182
+
183
+ # Get argument and verify type
184
+ # // luaL_argcheck could be better to report errors like "expected Mat"
185
+ def get_arg(arg, stack_pos)
186
+ type_def = "#{arg.create_type}#{arg.name}#{arg.array_suffix}"
187
+ if arg.is_native?
188
+ if arg.is_pointer?
189
+ if arg.type == 'char'
190
+ type_def = "const #{type_def}" unless arg.is_const?
191
+ "#{type_def} = luaL_checkstring(L, #{stack_pos});"
192
+ else
193
+ # retrieve by using a table accessor
194
+ # TODO: we should have a hint on required sizes !
195
+ "\nDubArgPointer<#{arg.type}> ptr_#{arg.name};\n" +
196
+ "#{type_def} = ptr_#{arg.name}(L, #{stack_pos});"
197
+ end
198
+ else
199
+ if FLOAT_TYPES.include?(arg.type)
200
+ "#{type_def} = luaL_checknumber(L, #{stack_pos});"
201
+ elsif INT_TYPES.include?(arg.type)
202
+ "#{type_def} = luaL_checkint(L, #{stack_pos});"
203
+ else
204
+ raise "Unsuported type: #{arg.type}"
205
+ end
206
+ end
207
+ else
208
+ "#{type_def} = *((#{arg.create_type}*)luaL_checkudata(L, #{stack_pos}, #{arg.id_name.inspect}));"
209
+ end
210
+ end
211
+
212
+ def flatten_hash(hash)
213
+ hash.each do |k, v|
214
+ if v.kind_of?(Hash)
215
+ hash[k] = flatten_hash(v)
216
+ end
217
+ end
218
+ hash.to_a.flatten
219
+ end
220
+
221
+ end # FunctionGen
222
+ end # Lua
223
+ end # Dub
@@ -0,0 +1,10 @@
1
+ <% @group.members.each do |f| %>
2
+ <%= function(f) %>
3
+
4
+ <% end %>
5
+
6
+ /** Overloaded function chooser for <%= @group.name %>(...) */
7
+ <%= signature(@group.first, 0) %> {
8
+ int type__ = lua_type(L, 1);
9
+ <%= indent(switch(Argument.decision_tree(@group.members)), 2) %>
10
+ }
@@ -0,0 +1,141 @@
1
+
2
+ #ifndef DOXY_GENERATOR_LIB_DOXY_GENERATOR_INCLUDE_LUA_DOXY_HELPER_H_
3
+ #define DOXY_GENERATOR_LIB_DOXY_GENERATOR_INCLUDE_LUA_DOXY_HELPER_H_
4
+
5
+ #include <stdlib.h> // malloc
6
+
7
+ #ifdef __cplusplus
8
+ extern "C" {
9
+ #endif
10
+ // We need C linkage because lua lib is compiled as C code
11
+ #include "lua.h"
12
+ #include "lauxlib.h"
13
+
14
+ #ifdef __cplusplus
15
+ }
16
+ #endif
17
+ /** ======================================== lua_pushclass */
18
+
19
+ /** Push a custom type on the stack.
20
+ * Since the value is passed as a pointer, we assume it has been created
21
+ * using 'new' and Lua can safely call delete when it needs to garbage-
22
+ * -collect it.
23
+ */
24
+ template<class T>
25
+ void lua_pushclass(lua_State *L, T *ptr, const char *type_name) {
26
+ T **userdata = (T**)lua_newuserdata(L, sizeof(T*));
27
+ *userdata = ptr;
28
+
29
+ // the userdata is now on top of the stack
30
+
31
+ // set metatable (contains methods)
32
+ luaL_getmetatable(L, type_name);
33
+ lua_setmetatable(L, -2);
34
+ }
35
+
36
+ /** Push a custom type on the stack.
37
+ * Since the value is passed by value, we have to allocate a copy
38
+ * using 'new' so that Lua can keep it.
39
+ */
40
+ template<class T>
41
+ void lua_pushclass(lua_State *L, T &val, const char *type_name) {
42
+ T *val_ptr = new T(val);
43
+ lua_pushclass<T>(L, val_ptr, type_name);
44
+ }
45
+
46
+ /** ======================================== DubArgPointer */
47
+
48
+ /** This class is a helper to provide pointer to data from
49
+ * Lua to C (but maybe it's not a good idea).
50
+ */
51
+ template<class T>
52
+ class DubArgPointer {
53
+ public:
54
+ DubArgPointer() : data(NULL) {}
55
+
56
+ ~DubArgPointer() {
57
+ if (data) free(data);
58
+ }
59
+
60
+ // TODO: we should have a hint on required sizes !
61
+ T *operator()(lua_State *L, int index) {
62
+ if (!lua_istable(L, index)) throw 1;
63
+
64
+ size_t size = lua_objlen(L, index);
65
+ if (size == 0) return NULL;
66
+
67
+ data = (T*)malloc(size * sizeof(T));
68
+ if (!data) throw 1;
69
+
70
+ for(size_t i=0; i < size; ++i) {
71
+ data[i] = get_value_at(L, index, i+1);
72
+ }
73
+ return data;
74
+ }
75
+
76
+ private:
77
+ T get_value_at(lua_State *L, int table_index, int index) {
78
+ lua_pushinteger(L, index + 1);
79
+ lua_gettable(L, index);
80
+ T value = luaL_checknumber(L, -1);
81
+ lua_pop(L, 1);
82
+ return value;
83
+ }
84
+
85
+ T *data;
86
+ };
87
+
88
+ /** ======================================== is_userdata */
89
+
90
+ inline bool is_userdata(lua_State *L, int index, const char *tname) {
91
+ void *p = lua_touserdata(L, index);
92
+ if (p != NULL) { /* value is a userdata? */
93
+ if (lua_getmetatable(L, index)) { /* does it have a metatable? */
94
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
95
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
96
+ lua_pop(L, 2); /* remove both metatables */
97
+ // type match
98
+ return true;
99
+ }
100
+ }
101
+ }
102
+ // type does not match
103
+ return false;
104
+ }
105
+
106
+ /** ======================================== register_constants */
107
+
108
+
109
+ typedef struct lua_constants_Reg {
110
+ const char *name;
111
+ double constant;
112
+ } lua_constants_Reg;
113
+
114
+ inline int libsize (const lua_constants_Reg *l) {
115
+ int size = 0;
116
+ for (; l->name; l++) size++;
117
+ return size;
118
+ }
119
+
120
+ inline void register_constants(lua_State *L, const char *name_space, const lua_constants_Reg *l) {
121
+ if (name_space) {
122
+ /* compute size hint for new table. */
123
+ int size = libsize(l);
124
+
125
+ /* try global variable (and create one if it does not exist) */
126
+ if (luaL_findtable(L, LUA_GLOBALSINDEX, name_space, size) != NULL)
127
+ luaL_error(L, "name conflict for module " LUA_QS, name_space);
128
+
129
+ /* found name_space in global index ==> stack -1 */
130
+ }
131
+ for (; l->name; l++) {
132
+ /* push each constant into the name_space (stack position = -1)*/
133
+ lua_pushnumber(L, l->constant);
134
+ lua_setfield(L, -2, l->name);
135
+ }
136
+ /* pop name_space */
137
+ lua_pop(L, 1);
138
+ }
139
+
140
+
141
+ #endif // DOXY_GENERATOR_LIB_DOXY_GENERATOR_INCLUDE_LUA_DOXY_HELPER_H_
@@ -0,0 +1,35 @@
1
+ #include "<%= @namespace.header %>"
2
+
3
+ #include "lua_cpp_helper.h"
4
+
5
+ using namespace <%= @namespace.name %>;
6
+
7
+ <% if @namespace.members; @namespace.members.each do |function| %>
8
+
9
+ <%= function %>
10
+
11
+ <% end; end %>
12
+
13
+ // Register namespace
14
+
15
+
16
+ static const struct luaL_Reg <%= @namespace.name %>_functions[] = {
17
+ <%= indent(functions_registration, 2) %>,
18
+ {NULL, NULL},
19
+ };
20
+
21
+ <% if @namespace.has_constants? %>
22
+ static const struct lua_constants_Reg <%= @namespace.name %>_namespace_constants[] = {
23
+ <%= indent(constants_registration, 2) %>,
24
+ {NULL, NULL},
25
+ };
26
+ <% end %>
27
+
28
+ void luaopen_<%= @namespace.lib_name %>(lua_State *L) {
29
+ // register functions
30
+ luaL_register(L, <%= @namespace.name.inspect %>, <%= @namespace.name %>_functions);
31
+ <% if @namespace.has_constants? %>
32
+ // register namespace enums
33
+ register_constants(L, <%= @namespace.id_name.inspect %>, <%= @namespace.name %>_namespace_constants);
34
+ <% end %>
35
+ }
@@ -0,0 +1,86 @@
1
+ require 'dub/generator'
2
+ require 'erb'
3
+
4
+ module Dub
5
+ module Lua
6
+ class NamespaceGen < Dub::Generator
7
+ def initialize
8
+ @namespace_template = ::ERB.new(File.read(File.join(File.dirname(__FILE__), 'namespace.cpp.erb')))
9
+ end
10
+
11
+ def namespace(namespace)
12
+ @namespace = namespace
13
+ @namespace_template.result(binding)
14
+ end
15
+
16
+ def class_generator
17
+ Lua.class_generator
18
+ end
19
+
20
+ def function_generator
21
+ Lua.function_generator
22
+ end
23
+
24
+ def functions_registration(namespace = @namespace)
25
+ (namespace.members || []).map do |method|
26
+ "{%-32s, #{method.method_name(0)}}" % method.name.inspect
27
+ end.join(",\n")
28
+ end
29
+
30
+ def constants_registration(namespace = @namespace)
31
+ res = []
32
+ if namespace.has_enums?
33
+ res << namespace.enums.map do |name|
34
+ "{%-32s, #{namespace.full_type}::#{name}}" % name.inspect
35
+ end.join(",\n")
36
+ end
37
+
38
+ if namespace.has_defines?
39
+ res << namespace.defines.map do |name|
40
+ "{%-32s, #{name}}" % name.inspect
41
+ end.join(",\n")
42
+ end
43
+
44
+ same = namespace.enums & namespace.defines
45
+ unless same.empty?
46
+ # Should never happen (not sure if it would compile ok in the first place)
47
+ puts "Warning: the following are present both as enum and define: #{same.inspect}"
48
+ end
49
+ res.join(",\n\n")
50
+ end
51
+
52
+ def members_list(all_members, ignore_list = [])
53
+ list = all_members.map do |member_or_group|
54
+ if ignore_list.include?(member_or_group.name)
55
+ nil
56
+ elsif member_or_group.kind_of?(Array)
57
+ members_list(member_or_group)
58
+ elsif ignore_member?(member_or_group)
59
+ nil
60
+ else
61
+ member_or_group
62
+ end
63
+ end
64
+
65
+ list.compact!
66
+ list == [] ? nil : list
67
+ end
68
+
69
+ def ignore_member?(member)
70
+ if member.name =~ /^~/ || # do not build constructor
71
+ member.name =~ /^operator/ || # no conversion operators
72
+ member.original_signature =~ />/ || # no complex types in signature
73
+ member.has_array_arguments? ||
74
+ member.vararg? ||
75
+ member.original_signature =~ /void\s+\*/
76
+ true # ignore
77
+ elsif return_value = member.return_value
78
+ return_value.type =~ />$/ || # no complex return types
79
+ return_value.is_native? && member.return_value.is_pointer?
80
+ else
81
+ false # ok, do not ignore
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
data/lib/dub/lua.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'dub/lua/function_gen'
2
+ require 'dub/lua/namespace_gen'
3
+ require 'dub/lua/class_gen'
4
+
5
+ module Dub
6
+ module Lua
7
+ def self.function_generator
8
+ @@function_generator ||= Dub::Lua::FunctionGen.new
9
+ end
10
+
11
+ def self.class_generator
12
+ @@class_generator ||= Dub::Lua::ClassGen.new
13
+ end
14
+
15
+ def self.namespace_generator
16
+ @@namespace_generator ||= Dub::Lua::NamespaceGen.new
17
+ end
18
+
19
+ def self.bind(object)
20
+ object.bind(self)
21
+ object
22
+ end
23
+ end # Lua
24
+ end # Dub
@@ -0,0 +1,88 @@
1
+ require 'dub/function'
2
+ require 'dub/function_group'
3
+ require 'dub/klass'
4
+
5
+ module Dub
6
+ class Klass
7
+ end
8
+
9
+ # This module is used by Namespace and Klass to extract member functions
10
+ module MemberExtraction
11
+ def members_prefix
12
+ @name
13
+ end
14
+
15
+ def parse_members
16
+ @members_hash = {}
17
+ @t_members_hash = {}
18
+ # TODO: template functions
19
+ (@xml/'memberdef').each do |member|
20
+ Dub.logger.info "Parsing #{member.name}"
21
+ name = (member/"name").innerHTML
22
+ if (member/'templateparamlist').first
23
+ insert_member(member, name, @t_members_hash)
24
+ else
25
+ insert_member(member, name, @members_hash)
26
+ end
27
+ end
28
+ end
29
+
30
+ def insert_member(member, name, destination)
31
+ if destination[name].kind_of?(Array)
32
+ destination[name] << member
33
+ elsif first_member = destination[name]
34
+ destination[name] = [first_member, member]
35
+ else
36
+ destination[name] = member
37
+ end
38
+ end
39
+
40
+ def member(name)
41
+ get_member(name.to_s)
42
+ end
43
+
44
+ def members
45
+ @members ||= begin
46
+ list = []
47
+ @members_hash.each do |name, member|
48
+ list << get_member(name)
49
+ end
50
+ list.compact!
51
+ list.sort
52
+ end
53
+ end
54
+
55
+ # Lazy construction of members
56
+ def get_member(name)
57
+ if member_or_group = @members_hash[name]
58
+ if member_or_group.kind_of?(Array)
59
+ if member_or_group.first.kind_of?(Hpricot::Elem)
60
+ list = Dub::FunctionGroup.new(self)
61
+ member_or_group.each_with_index do |m,i|
62
+ list << make_member(name, m, i + 1)
63
+ end
64
+ member_or_group = list.compact
65
+ member_or_group = nil if member_or_group == []
66
+ end
67
+ elsif member_or_group.kind_of?(Hpricot::Elem)
68
+ @members_hash[name] = member_or_group = make_member(name, member_or_group)
69
+ end
70
+ end
71
+ member_or_group
72
+ end
73
+
74
+ def make_member(name, member, overloaded_index = nil)
75
+ case member[:kind]
76
+ when 'function'
77
+ Dub.logger.info "Building #{members_prefix}::#{name}"
78
+ Function.new(self, name, member, members_prefix, overloaded_index)
79
+ when 'class'
80
+ Dub.logger.info "Building #{members_prefix}::#{name}"
81
+ Klass.new(self, name, member, members_prefix)
82
+ else
83
+ # not supported: ignore
84
+ nil
85
+ end
86
+ end
87
+ end
88
+ end # Dub