summaryrefslogtreecommitdiffstats
path: root/lib/tolua++/src/bin/lua/class.lua
blob: 592705282836cfb0c8215cadd5de26b308c8e12f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
-- tolua: class class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: $

-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.


-- Class class
-- Represents a class definition.
-- Stores the following fields:
--    name = class name
--    base = class base, if any (only single inheritance is supported)
--    {i}  = list of members
classClass = {
 classtype = 'class',
 name = '',
 base = '',
 type = '',
 btype = '',
 ctype = '',
}
classClass.__index = classClass
setmetatable(classClass,classContainer)


-- register class
function classClass:register (pre)

	if not self:check_public_access() then
		return
	end

 pre = pre or ''
 push(self)
	if _collect[self.type] then
		output(pre,'#ifdef __cplusplus\n')
  output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",'.._collect[self.type]..');')
		output(pre,'#else\n')
  output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);')
		output(pre,'#endif\n')
	else
  output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);')
	end
	if self.extra_bases then
		for k,base in ipairs(self.extra_bases) do
			-- not now
   --output(pre..' tolua_addbase(tolua_S, "'..self.type..'", "'..base..'");')
		end
	end
 output(pre..'tolua_beginmodule(tolua_S,"'..self.lname..'");')
 local i=1
 while self[i] do
  self[i]:register(pre..' ')
  i = i+1
 end
 output(pre..'tolua_endmodule(tolua_S);')
	pop()
end

-- return collection requirement
function classClass:requirecollection (t)
	if self.flags.protected_destructor or (not self:check_public_access()) then
		return false
	end
 push(self)
	local r = false
 local i=1
 while self[i] do
  r = self[i]:requirecollection(t) or r
  i = i+1
 end
	pop()
	-- only class that exports destructor can be appropriately collected
	-- classes that export constructors need to have a collector (overrided by -D flag on command line)
	if self._delete or ((not flags['D']) and self._new) then
		--t[self.type] = "tolua_collect_" .. gsub(self.type,"::","_")
		t[self.type] = "tolua_collect_" .. clean_template(self.type)
		r = true
	end
 return r
end

-- output tags
function classClass:decltype ()
 push(self)
	self.type = regtype(self.original_name or self.name)
	self.btype = typevar(self.base)
	self.ctype = 'const '..self.type
	if self.extra_bases then
		for i=1,table.getn(self.extra_bases) do
			self.extra_bases[i] = typevar(self.extra_bases[i])
		end
	end
 local i=1
 while self[i] do
  self[i]:decltype()
  i = i+1
 end
	pop()
end


-- Print method
function classClass:print (ident,close)
 print(ident.."Class{")
 print(ident.." name = '"..self.name.."',")
 print(ident.." base = '"..self.base.."';")
 print(ident.." lname = '"..self.lname.."',")
 print(ident.." type = '"..self.type.."',")
 print(ident.." btype = '"..self.btype.."',")
 print(ident.." ctype = '"..self.ctype.."',")
 local i=1
 while self[i] do
  self[i]:print(ident.." ",",")
  i = i+1
 end
 print(ident.."}"..close)
end

function classClass:set_protected_destructor(p)
	self.flags.protected_destructor = self.flags.protected_destructor or p
end

-- Internal constructor
function _Class (t)
 setmetatable(t,classClass)
 t:buildnames()
 append(t)
 return t
end

-- Constructor
-- Expects the name, the base (array) and the body of the class.
function Class (n,p,b)

	if table.getn(p) > 1 then
		b = string.sub(b, 1, -2)
		for i=2,table.getn(p),1 do
			b = b.."\n tolua_inherits "..p[i].." __"..p[i].."__;\n"
		end
		b = b.."\n}"
	end

	-- check for template
	b = string.gsub(b, "^{%s*TEMPLATE_BIND", "{\nTOLUA_TEMPLATE_BIND")
	local t,_,T,I = string.find(b, '^{%s*TOLUA_TEMPLATE_BIND%s*%(+%s*\"?([^\",]*)\"?%s*,%s*([^%)]*)%s*%)+')
	if t then

		-- remove quotes
		I = string.gsub(I, "\"", "")
		T = string.gsub(T, "\"", "")
		-- get type list
		local types = split_c_tokens(I, ",")
		-- remove TEMPLATE_BIND line
		local bs = string.gsub(b, "^{%s*TOLUA_TEMPLATE_BIND[^\n]*\n", "{\n")
			
		local Tl = split(T, " ")
		local tc = TemplateClass(n, p, bs, Tl)

		
		tc:throw(types, true)
		--for i=1,types.n do
		--	tc:throw(split_c_tokens(types[i], " "), true)
		--end
		return
	end
	
	local mbase

	if p then
		mbase = table.remove(p, 1)
		if not p[1] then p = nil end
	end

	mbase = mbase and resolve_template_types(mbase)

	local c
	local oname = string.gsub(n, "@.*$", "")
	oname = getnamespace(classContainer.curr)..oname

	if _global_classes[oname] then
		c = _global_classes[oname]
		if mbase and ((not c.base) or c.base == "") then
			c.base = mbase
		end
	else
		c = _Class(_Container{name=n, base=mbase, extra_bases=p})

		local ft = getnamespace(c.parent)..c.original_name
		append_global_type(ft, c)
	end

	push(c)
	c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
	pop()
end