summaryrefslogtreecommitdiff
path: root/src/lua/function.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua/function.lua')
-rw-r--r--src/lua/function.lua317
1 files changed, 317 insertions, 0 deletions
diff --git a/src/lua/function.lua b/src/lua/function.lua
new file mode 100644
index 00000000..b87e3488
--- /dev/null
+++ b/src/lua/function.lua
@@ -0,0 +1,317 @@
+-- tolua: function class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: function.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $
+
+-- 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.
+
+
+
+-- Function class
+-- Represents a function or a class method.
+-- The following fields are stored:
+-- mod = type modifiers
+-- type = type
+-- ptr = "*" or "&", if representing a pointer or a reference
+-- name = name
+-- args = list of argument declarations
+-- const = if it is a method receiving a const "this".
+classFunction = {
+ mod = '',
+ type = '',
+ ptr = '',
+ name = '',
+ args = {n=0},
+ const = '',
+ _base = classFeature,
+}
+settag(classFunction,tolua_tag)
+
+-- declare tags
+function classFunction:decltag ()
+ self.itype,self.tag = tagvar(self.type,strfind(self.mod,'const'))
+ local i=1
+ while self.args[i] do
+ self.args[i]:decltag()
+ i = i+1
+ end
+end
+
+
+-- Write binding function
+-- Outputs C/C++ binding function.
+function classFunction:supcode ()
+ local nret = 0 -- number of returned values
+ local class = self:inclass()
+ local _,_,static = strfind(self.mod,'^%s*(static)')
+
+ if class then
+ output("/* method:",self.name," of class ",class," */")
+ else
+ output("/* function:",self.name," */")
+ end
+ output("static int",self.cname,"(lua_State* tolua_S)")
+ output("{")
+
+ -- check types
+ output(' if (\n')
+ -- check self
+ local narg
+ if class then narg=2 else narg=1 end
+ if class and self.name~='new' and static==nil then
+ if self.const == 'const' then
+ output(' !tolua_istype(tolua_S,1,',self.parent.ctag,',0) ||\n')
+ else
+ output(' !tolua_istype(tolua_S,1,',self.parent.tag,',0) ||\n')
+ end
+ end
+ -- check args
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ if isbasic(self.args[i].type) ~= 'value' then
+ output(' !'..self.args[i]:outchecktype(narg)..' ||\n')
+ end
+ narg = narg+1
+ i = i+1
+ end
+ end
+ -- check end of list
+ output(' !tolua_isnoobj(tolua_S,'..narg..')\n )\n goto tolua_lerror;')
+
+ output(' else\n {')
+
+ -- declare self, if the case
+ local narg
+ if class then narg=2 else narg=1 end
+ if class and self.name~='new' and static==nil then
+ output(' ',self.const,class,'*','self = ')
+ output('(',self.const,class,'*) ')
+ output('tolua_getusertype(tolua_S,1,0);')
+ elseif static then
+ _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+ end
+ -- declare parameters
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ self.args[i]:declare(narg)
+ narg = narg+1
+ i = i+1
+ end
+ end
+
+ -- check self
+ if class and self.name~='new' and static==nil then
+ output(' if (!self) tolua_error(tolua_S,"invalid \'self\' in function \''..self.name..'\'");');
+ end
+
+ -- get array element values
+ if class then narg=2 else narg=1 end
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ self.args[i]:getarray(narg)
+ narg = narg+1
+ i = i+1
+ end
+ end
+
+ -- call function
+ if class and self.name=='delete' then
+ output(' delete self;')
+ elseif class and self.name == 'operator&[]' then
+ output(' self->operator[](',self.args[1].name,') = ',self.args[2].name,';')
+ else
+ output(' {')
+ if self.type ~= '' and self.type ~= 'void' then
+ output(' ',self.mod,self.type,self.ptr,'toluaI_ret = ')
+ output('(',self.mod,self.type,self.ptr,') ')
+ else
+ output(' ')
+ end
+ if class and self.name=='new' then
+ output('new',class,'(')
+ elseif class and static then
+ output(class..'::'..self.name,'(')
+ elseif class then
+ output('self->'..self.name,'(')
+ else
+ output(self.name,'(')
+ end
+
+ -- write parameters
+ local i=1
+ while self.args[i] do
+ self.args[i]:passpar()
+ i = i+1
+ if self.args[i] then
+ output(',')
+ end
+ end
+
+ output(');')
+
+ -- return values
+ if self.type ~= '' and self.type ~= 'void' then
+ nret = nret + 1
+ local t,ct = isbasic(self.type)
+ if t then
+ output(' tolua_push'..t..'(tolua_S,(',ct,')toluaI_ret);')
+ else
+ if self.ptr == '' then
+ output(' {')
+ output('#ifdef __cplusplus\n')
+ output(' void* toluaI_clone = new',self.type,'(toluaI_ret);')
+ output('#else\n')
+ output(' void* toluaI_clone = tolua_copy(tolua_S,(void*)&toluaI_ret,sizeof(',self.type,'));')
+ output('#endif\n')
+ output(' tolua_pushusertype(tolua_S,tolua_doclone(tolua_S,toluaI_clone,',self.tag,'),',self.tag,');')
+ output(' }')
+ --output(' tolua_pushclone((void*)&toluaI_ret,sizeof(',self.type,'),',self.tag,');')
+ elseif self.ptr == '&' then
+ output(' tolua_pushusertype(tolua_S,(void*)&toluaI_ret,',self.tag,');')
+ else
+ output(' tolua_pushusertype(tolua_S,(void*)toluaI_ret,',self.tag,');')
+ end
+ end
+ end
+ local i=1
+ while self.args[i] do
+ nret = nret + self.args[i]:retvalue()
+ i = i+1
+ end
+ output(' }')
+
+ -- set array element values
+ if class then narg=2 else narg=1 end
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ self.args[i]:setarray(narg)
+ narg = narg+1
+ i = i+1
+ end
+ end
+
+ -- free dynamically allocated array
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ self.args[i]:freearray()
+ i = i+1
+ end
+ end
+ end
+
+ output(' }')
+ output(' return '..nret..';')
+
+ -- call overloaded function or generate error
+ output('tolua_lerror:\n')
+ local overload = strsub(self.cname,-2,-1) - 1
+ if overload >= 0 then
+ output(' return '..strsub(self.cname,1,-3)..format("%02d",overload)..'(tolua_S);')
+ else
+ output(' tolua_error(tolua_S,"#ferror in function \''..self.lname..'\'.");')
+ output(' return 0;')
+ end
+
+ output('}')
+ output('\n')
+end
+
+-- register function
+function classFunction:register ()
+ local parent = self:inclass() or self:inmodule()
+ if parent then
+ output(' tolua_function(tolua_S,"'..parent..'","'..self.lname..'",'..self.cname..');')
+ else
+ output(' tolua_function(tolua_S,NULL,"'..self.lname..'",'..self.cname..');')
+ end
+end
+
+-- unregister function
+function classFunction:unregister ()
+ if self:inclass()==nil and self:inmodule()==nil then
+ output(' lua_pushnil(tolua_S); lua_setglobal(tolua_S,"'..self.lname..'");')
+ end
+end
+
+
+-- Print method
+function classFunction:print (ident,close)
+ print(ident.."Function{")
+ print(ident.." mod = '"..self.mod.."',")
+ print(ident.." type = '"..self.type.."',")
+ print(ident.." ptr = '"..self.ptr.."',")
+ print(ident.." name = '"..self.name.."',")
+ print(ident.." const = '"..self.const.."',")
+ print(ident.." cname = '"..self.cname.."',")
+ print(ident.." lname = '"..self.lname.."',")
+ print(ident.." args = {")
+ local i=1
+ while self.args[i] do
+ self.args[i]:print(ident.." ",",")
+ i = i+1
+ end
+ print(ident.." }")
+ print(ident.."}"..close)
+end
+
+-- determine lua function name overload
+function classFunction:overload ()
+ return self.parent:overload(self.lname)
+end
+
+
+
+-- Internal constructor
+function _Function (t)
+ t._base = classFunction
+ settag(t,tolua_tag)
+
+ if t.const ~= 'const' and t.const ~= '' then
+ error("#invalid 'const' specification")
+ end
+
+ append(t)
+ if t:inclass() then
+ if t.name == t.parent.name then
+ t.name = 'new'
+ t.lname = 'new'
+ t.type = t.parent.name
+ t.ptr = '*'
+ elseif t.name == '~'..t.parent.name then
+ t.name = 'delete'
+ t.lname = 'delete'
+ end
+ end
+ t.cname = t:cfuncname("toluaI")..t:overload(t)
+ return t
+end
+
+-- Constructor
+-- Expects three strings: one representing the function declaration,
+-- another representing the argument list, and the third representing
+-- the "const" or empty string.
+function Function (d,a,c)
+ local t = split(strsub(a,2,-2),',') -- eliminate braces
+ local i=1
+ local l = {n=0}
+ while t[i] do
+ l.n = l.n+1
+ l[l.n] = Declaration(t[i],'var')
+ i = i+1
+ end
+ local f = Declaration(d,'func')
+ f.args = l
+ f.const = c
+ return _Function(f)
+end
+
+