| [1650] | 1 | -- tolua: operator 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 | -- Operator class | 
|---|
|  | 14 | -- Represents an operator function or a class operator method. | 
|---|
|  | 15 | -- It stores the same fields as functions do plus: | 
|---|
|  | 16 | --  kind = set of character representing the operator (as it appers in C++ code) | 
|---|
|  | 17 | classOperator = { | 
|---|
| [2710] | 18 | kind = '', | 
|---|
| [1650] | 19 | } | 
|---|
|  | 20 | classOperator.__index = classOperator | 
|---|
|  | 21 | setmetatable(classOperator,classFunction) | 
|---|
|  | 22 |  | 
|---|
|  | 23 | -- table to transform operator kind into the appropriate tag method name | 
|---|
| [2710] | 24 | _TM = { | 
|---|
|  | 25 | ['+'] = 'add', | 
|---|
|  | 26 | ['-'] = 'sub', | 
|---|
|  | 27 | ['*'] = 'mul', | 
|---|
|  | 28 | ['/'] = 'div', | 
|---|
|  | 29 | ['<'] = 'lt', | 
|---|
|  | 30 | ['<='] = 'le', | 
|---|
|  | 31 | ['=='] = 'eq', | 
|---|
|  | 32 | ['[]'] = 'geti', | 
|---|
|  | 33 | ['&[]'] = 'seti', | 
|---|
|  | 34 | --['->'] = 'flechita', | 
|---|
|  | 35 | } | 
|---|
| [1650] | 36 |  | 
|---|
|  | 37 |  | 
|---|
|  | 38 | -- Print method | 
|---|
|  | 39 | function classOperator:print (ident,close) | 
|---|
| [2710] | 40 | print(ident.."Operator{") | 
|---|
|  | 41 | print(ident.." kind  = '"..self.kind.."',") | 
|---|
|  | 42 | print(ident.." mod  = '"..self.mod.."',") | 
|---|
|  | 43 | print(ident.." type = '"..self.type.."',") | 
|---|
|  | 44 | print(ident.." ptr  = '"..self.ptr.."',") | 
|---|
|  | 45 | print(ident.." name = '"..self.name.."',") | 
|---|
|  | 46 | print(ident.." const = '"..self.const.."',") | 
|---|
|  | 47 | print(ident.." cname = '"..self.cname.."',") | 
|---|
|  | 48 | print(ident.." lname = '"..self.lname.."',") | 
|---|
|  | 49 | print(ident.." args = {") | 
|---|
|  | 50 | local i=1 | 
|---|
|  | 51 | while self.args[i] do | 
|---|
|  | 52 | self.args[i]:print(ident.."  ",",") | 
|---|
|  | 53 | i = i+1 | 
|---|
|  | 54 | end | 
|---|
|  | 55 | print(ident.." }") | 
|---|
|  | 56 | print(ident.."}"..close) | 
|---|
| [1650] | 57 | end | 
|---|
|  | 58 |  | 
|---|
|  | 59 | function classOperator:supcode_tmp() | 
|---|
|  | 60 |  | 
|---|
| [2710] | 61 | if not _TM[self.kind] then | 
|---|
|  | 62 | return classFunction.supcode(self) | 
|---|
|  | 63 | end | 
|---|
| [1650] | 64 |  | 
|---|
| [2710] | 65 | -- no overload, no parameters, always inclass | 
|---|
|  | 66 | output("/* method:",self.name," of class ",self:inclass()," */") | 
|---|
| [1650] | 67 |  | 
|---|
| [2710] | 68 | output("#ifndef TOLUA_DISABLE_"..self.cname) | 
|---|
|  | 69 | output("\nstatic int",self.cname,"(lua_State* tolua_S)") | 
|---|
| [1650] | 70 |  | 
|---|
| [2710] | 71 | if overload < 0 then | 
|---|
|  | 72 | output('#ifndef TOLUA_RELEASE\n') | 
|---|
|  | 73 | end | 
|---|
|  | 74 | output(' tolua_Error tolua_err;') | 
|---|
|  | 75 | output(' if (\n') | 
|---|
|  | 76 | -- check self | 
|---|
|  | 77 | output('     !'..'tolua_isusertype(tolua_S,1,"'..self.parent.type..'",0,&tolua_err) ||\n') | 
|---|
|  | 78 | output('     !tolua_isnoobj(tolua_S,2,&tolua_err)\n )') | 
|---|
|  | 79 | output('  goto tolua_lerror;') | 
|---|
| [1650] | 80 |  | 
|---|
| [2710] | 81 | output(' else\n') | 
|---|
|  | 82 | output('#endif\n') -- tolua_release | 
|---|
|  | 83 | output(' {') | 
|---|
| [1650] | 84 |  | 
|---|
| [2710] | 85 | -- declare self | 
|---|
|  | 86 | output(' ',self.const,self.parent.type,'*','self = ') | 
|---|
|  | 87 | output('(',self.const,self.parent.type,'*) ') | 
|---|
|  | 88 | output('tolua_tousertype(tolua_S,1,0);') | 
|---|
| [1650] | 89 |  | 
|---|
| [2710] | 90 | -- check self | 
|---|
|  | 91 | output('#ifndef TOLUA_RELEASE\n') | 
|---|
|  | 92 | output('  if (!self) tolua_error(tolua_S,"invalid \'self\' in function \''..self.name..'\'",NULL);'); | 
|---|
|  | 93 | output('#endif\n') | 
|---|
| [1650] | 94 |  | 
|---|
| [2710] | 95 | -- cast self | 
|---|
|  | 96 | output('  ',self.mod,self.type,self.ptr,'tolua_ret = ') | 
|---|
|  | 97 | output('(',self.mod,self.type,self.ptr,')(*self);') | 
|---|
| [1650] | 98 |  | 
|---|
| [2710] | 99 | -- return value | 
|---|
|  | 100 | local t,ct = isbasic(self.type) | 
|---|
|  | 101 | if t then | 
|---|
|  | 102 | output('   tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);') | 
|---|
|  | 103 | else | 
|---|
|  | 104 | t = self.type | 
|---|
|  | 105 | new_t = string.gsub(t, "const%s+", "") | 
|---|
|  | 106 | if self.ptr == '' then | 
|---|
|  | 107 | output('   {') | 
|---|
|  | 108 | output('#ifdef __cplusplus\n') | 
|---|
|  | 109 | output('    void* tolua_obj = new',new_t,'(tolua_ret);') | 
|---|
|  | 110 | output('    tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");') | 
|---|
|  | 111 | output('#else\n') | 
|---|
|  | 112 | output('    void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));') | 
|---|
|  | 113 | output('    tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");') | 
|---|
|  | 114 | output('#endif\n') | 
|---|
|  | 115 | output('   }') | 
|---|
|  | 116 | elseif self.ptr == '&' then | 
|---|
|  | 117 | output('   tolua_pushusertype(tolua_S,(void*)&tolua_ret,"',t,'");') | 
|---|
|  | 118 | else | 
|---|
|  | 119 | if local_constructor then | 
|---|
|  | 120 | output('   tolua_pushusertype_and_takeownership(tolua_S,(void *)tolua_ret,"',t,'");') | 
|---|
|  | 121 | else | 
|---|
|  | 122 | output('   tolua_pushusertype(tolua_S,(void*)tolua_ret,"',t,'");') | 
|---|
|  | 123 | end | 
|---|
|  | 124 | end | 
|---|
|  | 125 | end | 
|---|
| [1650] | 126 |  | 
|---|
| [2710] | 127 | output('  }') | 
|---|
|  | 128 | output(' return 1;') | 
|---|
| [1650] | 129 |  | 
|---|
| [2710] | 130 | output('#ifndef TOLUA_RELEASE\n') | 
|---|
|  | 131 | output('tolua_lerror:\n') | 
|---|
|  | 132 | output(' tolua_error(tolua_S,"#ferror in function \''..self.lname..'\'.",&tolua_err);') | 
|---|
|  | 133 | output(' return 0;') | 
|---|
|  | 134 | output('#endif\n') | 
|---|
| [1650] | 135 |  | 
|---|
|  | 136 |  | 
|---|
| [2710] | 137 | output('}') | 
|---|
|  | 138 | output('#endif //#ifndef TOLUA_DISABLE\n') | 
|---|
|  | 139 | output('\n') | 
|---|
| [1650] | 140 | end | 
|---|
|  | 141 |  | 
|---|
|  | 142 | -- Internal constructor | 
|---|
|  | 143 | function _Operator (t) | 
|---|
| [2710] | 144 | setmetatable(t,classOperator) | 
|---|
| [1650] | 145 |  | 
|---|
| [2710] | 146 | if t.const ~= 'const' and t.const ~= '' then | 
|---|
|  | 147 | error("#invalid 'const' specification") | 
|---|
|  | 148 | end | 
|---|
| [1650] | 149 |  | 
|---|
| [2710] | 150 | append(t) | 
|---|
|  | 151 | if not t:inclass() then | 
|---|
|  | 152 | error("#operator can only be defined as class member") | 
|---|
|  | 153 | end | 
|---|
| [1650] | 154 |  | 
|---|
| [2710] | 155 | --t.name = t.name .. "_" .. (_TM[t.kind] or t.kind) | 
|---|
|  | 156 | t.cname = t:cfuncname("tolua")..t:overload(t) | 
|---|
|  | 157 | t.name = "operator" .. t.kind  -- set appropriate calling name | 
|---|
|  | 158 | return t | 
|---|
| [1650] | 159 | end | 
|---|
|  | 160 |  | 
|---|
|  | 161 | -- Constructor | 
|---|
|  | 162 | function Operator (d,k,a,c) | 
|---|
|  | 163 |  | 
|---|
| [2710] | 164 | local op_k = string.gsub(k, "^%s*", "") | 
|---|
|  | 165 | op_k = string.gsub(k, "%s*$", "") | 
|---|
|  | 166 | --if string.find(k, "^[%w_:%d<>%*%&]+$") then | 
|---|
|  | 167 | if d == "operator" and k ~= '' then | 
|---|
| [1650] | 168 |  | 
|---|
| [2710] | 169 | d = k.." operator" | 
|---|
|  | 170 | elseif not _TM[op_k] then | 
|---|
| [1650] | 171 |  | 
|---|
| [2710] | 172 | if flags['W'] then | 
|---|
|  | 173 | error("tolua: no support for operator" .. f.kind) | 
|---|
|  | 174 | else | 
|---|
|  | 175 | warning("No support for operator "..op_k..", ignoring") | 
|---|
|  | 176 | return nil | 
|---|
|  | 177 | end | 
|---|
|  | 178 | end | 
|---|
| [1650] | 179 |  | 
|---|
| [2710] | 180 | local ref = '' | 
|---|
|  | 181 | local t = split_c_tokens(strsub(a,2,strlen(a)-1),',') -- eliminate braces | 
|---|
|  | 182 | local i=1 | 
|---|
|  | 183 | local l = {n=0} | 
|---|
|  | 184 | while t[i] do | 
|---|
|  | 185 | l.n = l.n+1 | 
|---|
|  | 186 | l[l.n] = Declaration(t[i],'var') | 
|---|
|  | 187 | i = i+1 | 
|---|
|  | 188 | end | 
|---|
|  | 189 | if k == '[]' then | 
|---|
|  | 190 | local _ | 
|---|
|  | 191 | _, _, ref = strfind(d,'(&)') | 
|---|
|  | 192 | d = gsub(d,'&','') | 
|---|
|  | 193 | elseif k=='&[]' then | 
|---|
|  | 194 | l.n = l.n+1 | 
|---|
|  | 195 | l[l.n] = Declaration(d,'var') | 
|---|
|  | 196 | l[l.n].name = 'tolua_value' | 
|---|
|  | 197 | end | 
|---|
|  | 198 | local f = Declaration(d,'func') | 
|---|
|  | 199 | if k == '[]' and (l[1]==nil or isbasic(l[1].type)~='number') then | 
|---|
|  | 200 | error('operator[] can only be defined for numeric index.') | 
|---|
|  | 201 | end | 
|---|
|  | 202 | f.args = l | 
|---|
|  | 203 | f.const = c | 
|---|
|  | 204 | f.kind = op_k | 
|---|
|  | 205 | f.lname = "."..(_TM[f.kind] or f.kind) | 
|---|
|  | 206 | if not _TM[f.kind] then | 
|---|
|  | 207 | f.cast_operator = true | 
|---|
|  | 208 | end | 
|---|
|  | 209 | if f.kind == '[]' and ref=='&' and f.const~='const' then | 
|---|
|  | 210 | Operator(d,'&'..k,a,c)     -- create correspoding set operator | 
|---|
|  | 211 | end | 
|---|
|  | 212 | return _Operator(f) | 
|---|
| [1650] | 213 | end | 
|---|
|  | 214 |  | 
|---|
|  | 215 |  | 
|---|