1 | -- tolua: class class |
---|
2 | -- Written by Waldemar Celes |
---|
3 | -- TeCGraf/PUC-Rio |
---|
4 | -- Jul 1998 |
---|
5 | -- $Id: $ |
---|
6 | |
---|
7 | -- This code is free software; you can redistribute it and/or modify it. |
---|
8 | -- The software provided hereunder is on an "as is" basis, and |
---|
9 | -- the author has no obligation to provide maintenance, support, updates, |
---|
10 | -- enhancements, or modifications. |
---|
11 | |
---|
12 | |
---|
13 | -- Class class |
---|
14 | -- Represents a class definition. |
---|
15 | -- Stores the following fields: |
---|
16 | -- name = class name |
---|
17 | -- base = class base, if any (only single inheritance is supported) |
---|
18 | -- {i} = list of members |
---|
19 | classClass = { |
---|
20 | classtype = 'class', |
---|
21 | name = '', |
---|
22 | base = '', |
---|
23 | type = '', |
---|
24 | btype = '', |
---|
25 | ctype = '', |
---|
26 | } |
---|
27 | classClass.__index = classClass |
---|
28 | setmetatable(classClass,classContainer) |
---|
29 | |
---|
30 | |
---|
31 | -- register class |
---|
32 | function classClass:register (pre) |
---|
33 | if not self:check_public_access() then |
---|
34 | return |
---|
35 | end |
---|
36 | |
---|
37 | pre = pre or '' |
---|
38 | push(self) |
---|
39 | if _collect[self.type] then |
---|
40 | output(pre,'#ifdef __cplusplus\n') |
---|
41 | output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",'.._collect[self.type]..');') |
---|
42 | output(pre,'#else\n') |
---|
43 | output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);') |
---|
44 | output(pre,'#endif\n') |
---|
45 | else |
---|
46 | output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);') |
---|
47 | end |
---|
48 | if self.extra_bases then |
---|
49 | for k,base in ipairs(self.extra_bases) do |
---|
50 | -- not now |
---|
51 | --output(pre..' tolua_addbase(tolua_S, "'..self.type..'", "'..base..'");') |
---|
52 | end |
---|
53 | end |
---|
54 | output(pre..'tolua_beginmodule(tolua_S,"'..self.lname..'");') |
---|
55 | local i=1 |
---|
56 | while self[i] do |
---|
57 | self[i]:register(pre..' ') |
---|
58 | i = i+1 |
---|
59 | end |
---|
60 | output(pre..'tolua_endmodule(tolua_S);') |
---|
61 | pop() |
---|
62 | end |
---|
63 | |
---|
64 | -- return collection requirement |
---|
65 | function classClass:requirecollection (t) |
---|
66 | if self.flags.protected_destructor then |
---|
67 | return false |
---|
68 | end |
---|
69 | push(self) |
---|
70 | local r = false |
---|
71 | local i=1 |
---|
72 | while self[i] do |
---|
73 | r = self[i]:requirecollection(t) or r |
---|
74 | i = i+1 |
---|
75 | end |
---|
76 | pop() |
---|
77 | -- only class that exports destructor can be appropriately collected |
---|
78 | -- classes that export constructors need to have a collector (overrided by -D flag on command line) |
---|
79 | if self._delete or ((not flags['D']) and self._new) then |
---|
80 | --t[self.type] = "tolua_collect_" .. gsub(self.type,"::","_") |
---|
81 | t[self.type] = "tolua_collect_" .. clean_template(self.type) |
---|
82 | r = true |
---|
83 | end |
---|
84 | return r |
---|
85 | end |
---|
86 | |
---|
87 | -- output tags |
---|
88 | function classClass:decltype () |
---|
89 | push(self) |
---|
90 | self.type = regtype(self.original_name or self.name) |
---|
91 | self.btype = typevar(self.base) |
---|
92 | self.ctype = 'const '..self.type |
---|
93 | if self.extra_bases then |
---|
94 | for i=1,table.getn(self.extra_bases) do |
---|
95 | self.extra_bases[i] = typevar(self.extra_bases[i]) |
---|
96 | end |
---|
97 | end |
---|
98 | local i=1 |
---|
99 | while self[i] do |
---|
100 | self[i]:decltype() |
---|
101 | i = i+1 |
---|
102 | end |
---|
103 | pop() |
---|
104 | end |
---|
105 | |
---|
106 | |
---|
107 | -- Print method |
---|
108 | function classClass:print (ident,close) |
---|
109 | print(ident.."Class{") |
---|
110 | print(ident.." name = '"..self.name.."',") |
---|
111 | print(ident.." base = '"..self.base.."';") |
---|
112 | print(ident.." lname = '"..self.lname.."',") |
---|
113 | print(ident.." type = '"..self.type.."',") |
---|
114 | print(ident.." btype = '"..self.btype.."',") |
---|
115 | print(ident.." ctype = '"..self.ctype.."',") |
---|
116 | local i=1 |
---|
117 | while self[i] do |
---|
118 | self[i]:print(ident.." ",",") |
---|
119 | i = i+1 |
---|
120 | end |
---|
121 | print(ident.."}"..close) |
---|
122 | end |
---|
123 | |
---|
124 | function classClass:set_protected_destructor(p) |
---|
125 | self.flags.protected_destructor = self.flags.protected_destructor or p |
---|
126 | end |
---|
127 | |
---|
128 | -- Internal constructor |
---|
129 | function _Class (t) |
---|
130 | setmetatable(t,classClass) |
---|
131 | t:buildnames() |
---|
132 | append(t) |
---|
133 | return t |
---|
134 | end |
---|
135 | |
---|
136 | -- Constructor |
---|
137 | -- Expects the name, the base (array) and the body of the class. |
---|
138 | function Class (n,p,b) |
---|
139 | |
---|
140 | if table.getn(p) > 1 then |
---|
141 | b = string.sub(b, 1, -2) |
---|
142 | for i=2,table.getn(p),1 do |
---|
143 | b = b.."\n tolua_inherits "..p[i].." __"..p[i].."__;\n" |
---|
144 | end |
---|
145 | b = b.."\n}" |
---|
146 | end |
---|
147 | |
---|
148 | -- check for template |
---|
149 | b = string.gsub(b, "^{%s*TEMPLATE_BIND", "{\nTOLUA_TEMPLATE_BIND") |
---|
150 | local t,_,T,I = string.find(b, "^{%s*TOLUA_TEMPLATE_BIND%s*%(+%s*\"?([^\",]*)\"?%s*,%s*([^%)]*)%s*%)+") |
---|
151 | if t then |
---|
152 | |
---|
153 | -- remove quotes |
---|
154 | I = string.gsub(I, "\"", "") |
---|
155 | T = string.gsub(T, "\"", "") |
---|
156 | -- get type list |
---|
157 | local types = split_c_tokens(I, ",") |
---|
158 | -- remove TEMPLATE_BIND line |
---|
159 | local bs = string.gsub(b, "^{%s*TOLUA_TEMPLATE_BIND[^\n]*\n", "{\n") |
---|
160 | |
---|
161 | -- replace |
---|
162 | for i =1 , types.n do |
---|
163 | |
---|
164 | local Tl = split(T, " ") |
---|
165 | local Il = split_c_tokens(types[i], " ") |
---|
166 | local bI = bs |
---|
167 | local pI = {} |
---|
168 | for j = 1,Tl.n do |
---|
169 | Tl[j] = findtype(Tl[j]) or Tl[j] |
---|
170 | bI = string.gsub(bI, "([^_%w])"..Tl[j].."([^_%w])", "%1"..Il[j].."%2") |
---|
171 | if p then |
---|
172 | for i=1,table.getn(p) do |
---|
173 | pI[i] = string.gsub(p[i], "([^_%w]?)"..Tl[j].."([^_%w]?)", "%1"..Il[j].."%2") |
---|
174 | end |
---|
175 | end |
---|
176 | end |
---|
177 | --local append = "<"..string.gsub(types[i], "%s+", ",")..">" |
---|
178 | local append = "<"..concat(Il, 1, table.getn(Il), ",")..">" |
---|
179 | append = string.gsub(append, "%s*,%s*", ",") |
---|
180 | append = string.gsub(append, ">>", "> >") |
---|
181 | for i=1,table.getn(pI) do |
---|
182 | --pI[i] = string.gsub(pI[i], ">>", "> >") |
---|
183 | pI[i] = resolve_template_types(pI[i]) |
---|
184 | end |
---|
185 | bI = string.gsub(bI, ">>", "> >") |
---|
186 | Class(n..append, pI, bI) |
---|
187 | end |
---|
188 | return |
---|
189 | end |
---|
190 | |
---|
191 | local mbase |
---|
192 | |
---|
193 | if p then |
---|
194 | mbase = table.remove(p, 1) |
---|
195 | if not p[1] then p = nil end |
---|
196 | end |
---|
197 | |
---|
198 | mbase = mbase and resolve_template_types(mbase) |
---|
199 | |
---|
200 | local c |
---|
201 | local oname = string.gsub(n, "@.*$", "") |
---|
202 | oname = getnamespace(classContainer.curr)..oname |
---|
203 | |
---|
204 | if _global_classes[oname] then |
---|
205 | c = _global_classes[oname] |
---|
206 | if mbase and ((not c.base) or c.base == "") then |
---|
207 | c.base = mbase |
---|
208 | end |
---|
209 | else |
---|
210 | c = _Class(_Container{name=n, base=mbase, extra_bases=p}) |
---|
211 | |
---|
212 | local ft = getnamespace(c.parent)..c.original_name |
---|
213 | append_global_type(ft, c) |
---|
214 | end |
---|
215 | |
---|
216 | push(c) |
---|
217 | c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces |
---|
218 | pop() |
---|
219 | end |
---|
220 | |
---|