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