lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Wow.

Here's what I tried:
[rwebb@collective lua2c]$ more test.lua
if g[t] then
    return g[t]
else
    return 4*4
end
g.xxx = sqrt(4)

[rwebb@collective lua2c]$ ../luac -p -l test.lua | ../lua lua2c.lua
 lua_getglobal(L,"g");
 lua_getglobal(L,"t");
 lua_gettable(L,-2);
 lua_remove(L,-2);
#error cannot handle JMPF
 lua_getglobal(L,"g");
 lua_getglobal(L,"t");
 lua_gettable(L,-2);
 lua_remove(L,-2);
 return 2;
#error cannot handle JMP
 lua_pushnumber(L,4);
 lua_pushnumber(L,4);
#error cannot handle MULT
 return 2;
 lua_getglobal(L,"g");
 lua_pushstring(L,"xxx");
 lua_getglobal(L,"sqrt");
 lua_pushnumber(L,4);
 lua_call(L,1,1);
 lua_settable(L,-2);
 lua_remove(L,-2);

Looks fairly good!  If nothing else it's instructive and could be really
helpful in writing C code.  A couple of ideas:

1.  Handling conditionals would be amazing though it does complicate things
a bit; shouldn't be terribly hard.

2.  Instead of "#error cannot handle MULT" how about
lua2c_MULT_encountered(); so that someone can implement that C function and
the C code will compile!

3. Could it be built into luac one day?  That would make it more easily
available.

4. Being able to specify a function to convert by name from within Lua and
to get back a string would be nice for automated build systems.  Something
like:

function tmp(x)
    ... some lua code
end
cSource = lua2c(tmp)
tmp = nil
-- now write cSource to a .c file will all the added code to make it a C
function bound to lua

Or some such way to auto-generate C files.  That way one can create a Lua
build system such that some of the C code is automatically ported to the
next version of Lua!

Cool stuff.

Russ


> From: Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
> Date: Thu, 24 Jan 2002 15:05:06 -0200
> To: rw20@cornell.edu (Russell Y Webb)
> Subject: Re: Lua to C (was 4.1 work3 lua_getGlobal)
> 
>> Since there's a fairly 1:1 correspondence between lua code and the C API
>> have you ever considered writing a Lua to C compiler?  C is presumably a bit
>> faster, much more easily protected from change, and needed for interfacing
>> to most external APIs.  Perhaps disassembling the bytes codes to C would be
>> easy?
> 
> I've had a crack at this. See below. I'm still working on it, but I'd like
> your opinion. Thanks.
> --lhf
> 
> -- lua2c.lua
> -- Generates C code from Lua code
> -- usage: luac -p -l myfile.lua | lua lua2c.lua
> -- assumes luac from 4.0
> 
> INDENT=" "
> SP=0
> 
> function stack(n)
> SP=SP+n
> debug("SP=",SP,"\n")
> end
> 
> function NOP(op,p1,p2,c)
> end
> 
> function END(op,p1,p2,c)
> SP=0
> write("\n/***********************************************************/\n")
> end
> 
> function CANNOT(op,p1,p2,c)
> --write("#error cannot handle ",op,"\n")
> --exit(1)
> end
> 
> function RETURN(op,p1,p2,c)
> write(INDENT,'return ',SP-p1,';\n')
> stack(-(SP-p1))
> end
> 
> function CALL(op,p1,p2,c)
> write(INDENT,'lua_call(L,',-(p1+1),',',p2,');\n')
> stack(p2-(SP-p1))
> end
> 
> function POP(op,p1,p2,c)
> write(INDENT,'lua_pop(L,',p1,');\n')
> stack(1)
> end
> 
> function PUSHNIL(op,p1,p2,c)
> write(INDENT,'lua_pushnil(L);\n')
> stack(1)
> end
> 
> function PUSHINT(op,p1,p2,c)
> write(INDENT,'lua_pushnumber(L,',p1,');\n')
> stack(1)
> end
> 
> function PUSHSTRING(op,p1,p2,c)
> write(INDENT,'lua_pushstring(L,"',c,'");\n')
> stack(1)
> end
> 
> function PUSHNUM(op,p1,p2,c)
> write(INDENT,'lua_pushnumber(L,',c,');\n')
> stack(1)
> end
> 
> function PUSHNEGNUM(op,p1,p2,c)
> write(INDENT,'lua_pushnumber(L,-',c,');\n')
> stack(1)
> end
> 
> function GETLOCAL(op,p1,p2,c)
> write(INDENT,'lua_pushvalue(L,',p1+1,');\n')
> stack(1)
> end
> 
> function GETGLOBAL(op,p1,p2,c)
> write(INDENT,'lua_getglobal(L,"',c,'");\n')
> stack(1)
> end
> 
> function GETTABLE(op,p1,p2,c)
> write(INDENT,'lua_gettable(L,-2);\n')
> write(INDENT,'lua_remove(L,-2);\n')
> stack(-1)
> end
> 
> function GETDOTTED(op,p1,p2,c)
> write(INDENT,'lua_pushstring(L,"',c,'");\n')
> write(INDENT,'lua_gettable(L,-2);\n')
> write(INDENT,'lua_remove(L,-2);\n')
> stack(0)
> end
> 
> function PUSHSELF(op,p1,p2,c)
> write(INDENT,'lua_pushstring(L,"',c,'");\n')
> write(INDENT,'lua_gettable(L,-2);\n')
> write(INDENT,'lua_insert(L,-2);\n')
> stack(1)
> end
> 
> function CREATETABLE(op,p1,p2,c)
> write(INDENT,'lua_newtable(L);\n')
> stack(1)
> end
> 
> function SETGLOBAL(op,p1,p2,c)
> write(INDENT,'lua_setglobal(L,"',c,'");\n')
> stack(-1)
> end
> 
> function SETTABLE(op,p1,p2,c)
> write(INDENT,'lua_settable(L,-2);\n')
> write(INDENT,'lua_remove(L,-2);\n')
> stack(-1)
> end
> 
> function CONCAT(op,p1,p2,c)
> write(INDENT,'lua_concat(L,',p1,');\n')
> stack(-p1+1)
> end
> 
> function SETLIST(op,p1,p2,c)
> for i=p1+1,p1+p2 do
> write(INDENT,'lua_pushnumber(L,',i,');\n')
> write(INDENT,'lua_insert(L,-2);\n')
> write(INDENT,'lua_settable(L,',-p2-2,');\n')
> end
> stack(-p2)
> end
> 
> function SETMAP(op,p1,p2,c)
> for i=1,p1 do
> write(INDENT,'lua_settable(L,',-2*(p1-i+1)-1,');\n')
> end
> stack(-2*p1)
> end
> 
> debug=write
> debug=NOP
> 
> while 1 do
> local s=read()
> if s==nil then break end
> local _,_,n=strfind(s,"^(%d+) params")
> if n~=nil then SP=n end
> debug(s,"\n")
> local p='%s*(%d+)%s+%[(%d+)%]%s+(%w+)%s+(%w*)%s*(%w*)%s*;?%s*"?(.-)"?%s*$'
> local _,_,pc,ln,op,p1,p2,c=strfind(s,p)
> --print(pc,ln,op,p1,p2,c)
> if op~=nil then
> debug(s,"\n")
> local f=getglobal(op) or CANNOT
> f(op,tonumber(p1),tonumber(p2),c)
> end
> end