[2072] | 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 | |
---|