| 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 |  | 
|---|