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