dub 0.5.0

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.

Potentially problematic release.


This version of dub might be problematic. Click here for more details.

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