• About
    • Resume
A Game Developer also plays some guitar

Tag Archives: Eval

Lua相关问题整理(4) – 让Lua的eval函数支持赋值语句

November 28, 2010 12:22 pm / Benny Chen

上一篇文章提到了在Lua中实现类似于JavaScript中的eval函数,遗憾是该eval函数不支持赋值语句,原因是Lua的赋值运算符是不支持返回值。所以如果要让该eval函数也支持赋值语句,就需要一个额外的工作,让它鉴别一个语句是不是赋值语句,如果是,则return的是被赋值后变量的值。为此,我写了一个isAssignmentExpression函数,比较粗糙,不过够用了,基本思想是检测语句中第一个出现的”=“操作符,且该”=“不能在一对引号当中。

[js collapse=”true”]
— Lua code
function isAssignmentExpression( str )
local i = 1;
local curChar;
local quotesType = "none" — none, single or double
local isEscaping = false

curChar = string.sub( str, 1, 1 )
while ( curChar ~= "" ) do
if ( curChar == "’" and
isEscaping == false and
quotesType ~= "double" )
then
if ( quotesType == "single" )
then quotesType = "none"
elseif ( quotesType == "none" )
then quotesType = "single"
end
end

if ( curChar == """ and
isEscaping == false and
quotesType ~= "single" )
then
if ( quotesType == "double" )
then quotesType = "none"
elseif ( quotesType == "none" )
then quotesType = "double"
end
end

if ( curChar == "\" and isEscaping == false )
then isEscaping = true
else isEscaping = false
end

if ( curChar == "=" and quotesType == "none" )
then
if ( string.sub( str, i+1, i+1 ) ~= "=" )
then
return true, string.sub( str, 1, i – 1 )
else
return false
end
end

i = i + 1
curChar = string.sub( str, i, i )
end

return false
end

function eval( str )
local bAssign
local var
bAssign, var = isAssignmentExpression( str )
if ( bAssign )
then
print( "Assignment, var=" .. var )
loadstring( str )()
return loadstring( "return " .. var )()
else
return loadstring( "return " .. str )()
end
end

— 以下是一组测试
print( eval( "3+4" ) )
— 7
function Multiply( a, b )
return a*b
end
print( eval( "Multiply( 3, 4 )" ) )
— 12
print( eval( "i" ) )
— nil
print( eval( "i = 1" ) )
— Assignment, var=i
— 1
print( eval( "i = i + 1" ) )
— Assignment, var=i
— 2
print( eval( "i" ) )
— 2
print( eval( "i+1" ) )
— 3
print( eval( "i, j = 4, 5" ) )
— Assignment, var=i, j
— 4 5
print( eval( "i = {}" ) )
— Assignment, var=i
— table: 003CD818
print( eval( "i[ "0" ] = 0" ) )
— Assignment, var=i[ "0" ]
— 0
print( eval( "i[ "\"0=" ] = 1" ) )
— Assignment, var=i[ ""0=" ]
— 1
print( eval( "i.name="hello"" ) )
— Assignment, var=i.name
— hello
print( eval( "i[0], i.name = 4" ) )
— Assignment, var=i[0], i.name
— 4 nil
print( eval( "i == 10" ) )
— false
[/js]

Posted in: Game Programming, Lua / Tagged: eval, lua, 赋值语句

Lua相关问题整理(3)

November 27, 2010 5:04 pm / Benny Chen
  1. 在注册给Lua的C函数中为Lua提供默认参数

    使用luaL_optstring, luaL_optnumber, luaL_optinteger等Lua API,如下示例,函数有一个默认字符串参数,默认值为””,这样在Lua中调用whatever的时候,whatever()或者whatever( “whatever”)均可。(Oh…whatever…随便…都行…)
    [cpp]
    // C code
    int Whatever( lua_State *L )
    {
    string str = luaL_optstring( L, 1, "" );
    //…omitted code…
    }
    lua_register( L, "whatever", Whatever );
    [/cpp]

  2. 建立Lua字符串到C enum的映射

  3. 使用luaL_checkoption这个Lua API,它可以把从Lua传来的string转换为相应的C string array中的index,从而可以建立Lua字符串和C enum的映射。以下是个简单的示例:
    [cpp]
    // C code
    enum PlayerType
    {
    PLAYER_TYPE_UNDEFINED = -1,
    PLAYER_TYPE_KING = 0, // 主公
    PLAYER_TYPE_INSURGENT, // 反贼
    PLAYER_TYPE_LOYAL, // 忠臣
    PLAYER_TYPE_TREACHEROUS, //内奸-_^
    NUM_PLAYER_TYPE // just a sentinel
    };

    const char * const PlayerTypeList[NUM_PLAYER_TYPE + 1] =
    {
    "KING",
    "INSURGENT",
    "LOYAL",
    "TREACHEROUS",
    NULL
    };

    static int testPlayerType( lua_State *L )
    {
    PlayerType type = static_cast< PlayerType >(
    luaL_checkoption( L, 1,
    "INSURGENT", PlayerTypeList ) );
    std::cout << "Type index is " << type
    << " – " << PlayerTypeList[type]
    << std::endl;
    return 0;
    }

    lua_register( L, "setPlayerType", setPlayerType )
    [/cpp]
    首先enum PlayerType定义了一组角色类型,来自人人都爱的三国杀:-)。

    接着PlayerTypeList定义了一个字符串数组,给Lua使用。注意需要保证enum和字符串数组的对应,比如PlayerTypeList[PLAYER_TYPE_KING]是“KING”,同时,PlayerTypeList必须以NULL结尾。

    在定义给Lua的函数testPlayerType中,就可以用luaL_checkoption将Lua传来的字符串参数转换为相应enum的值。luaL_checkoption还支持默认参数,比如在上面例子中,将第三个参数设为“INSURGENT”,如果Lua中没有提供任何参数,则PlayerType就为与“INSURGENT”相对应的PLAYER_TYPE_INSURGENT。

    以下是一组测试及结果:
    [js]
    –Lua code
    testPlayerType( "KING" ) — Type index is 0 – KING
    testPlayerType() — Type index is 1 – INSURGENT
    testPlayerType( "whatever" ) — bad argument #1 to ‘testPlayerType’ (invalid option ‘whatever’)
    [/js]

  4. 在Lua中实现eval函数

    众所周知,JavaScript中有一个著名的eval函数,它用于把一个字符串当作一段JS代码去执行,在Lua中没有提供类似的函数,但稍微包装下Lua的库函数loadstring即可实现,以下是代码。
    [js]
    –Lua code
    function eval( str )
    local func = loadstring( "return " ..str );
    return func()
    end
    [/js]
    这样已经可以了,不过相比于JS的eval函数,功能稍微差一些,因为它不支持赋值语句,这是Lua语言天然的原因,因为Lua的赋值运算符没有返回值,在其他语言中常见传递赋值的“i=j=1”(先赋值j=1,然后将(j=1)的返回值j赋值给i),在Lua中是不允许的。所以当eval执行的是赋值运算(比如i=1)的时候,return i=1就会出错。

    下面是一些测试例子:
    [js]
    –Lua code
    print( eval( "3+4" ) ) — OK, 打印7

    function Multiply( a, b )
    return a*b
    end

    print( eval( "Multiply( 3, 4 )" ) ) — OK,打印12

    print( eval( "i = 1" ) ) — 错误, attempt to call a nil value
    i = 1
    print( eval( "i" ) ) — OK,打印1
    print( eval( "i = i + 1" ) ) — 错误, attempt to call a nil value
    [/js]

  5. 实现luaL_checkbool

    不知道为什么Lua的API没有提供luaL_checkbook函数,不过很容易实现:
    [cpp]
    // C code
    BOOL luaL_checkbool( lua_State *luaVM, int numArg )
    {
    BOOL b = FALSE;
    if ( lua_type( L, numArg ) == LUA_TBOOLEAN )
    {
    b = lua_toboolean( L, numArg );
    }
    else
    {
    luaL_typerror( L, numArg, lua_typename( L, LUA_TBOOLEAN ) )
    }
    return b;
    }
    [/cpp]

Posted in: C++, Game Programming, Lua / Tagged: enum, eval, lua, luaL_checkbool, 默认参数

Categories

  • In My Life (25)
    • A Day in the Life (8)
    • English Learning (2)
    • Learn a Word (7)
    • Something In The Way (8)
  • Music Heaven (8)
    • Guitar (1)
    • In Concert (1)
    • Lyrics (3)
  • OK Computer (54)
    • 3D (3)
    • C++ (10)
    • Computer Graphics (15)
    • Game Programming (23)
    • iOS (6)
    • Linux (1)
    • Lua (9)
    • My Projects (3)
    • Some Experiences (9)
    • Talking in Code (2)
    • Unity (2)
  • Quotations (2)
  • Uncategorized (1)
  • Visca Barça (24)
    • FCB BJ (5)

Recent Posts

  • [译]优化你的手机游戏(没有延迟的,才是健康的)- 一篇给游戏美术设计师读的文章
  • 新浪微博API for MOAI
  • 稍后继续
  • Unity Developer ++
  • Another Thread @ Moai Forum
  • 1st Day of Golden Week
  • 为SyntaxHighlighter添加新语言
  • 基于Lua的State Pattern
  • Class Diagram of Pacman
  • 基于Moai的Pacman

Recent Comments

  • 约修亚_RK on 为SyntaxHighlighter添加新语言
  • 爱装的小男孩 on 小心DLL链接静态库时的内存错误
  • happyfire on Game Loop的几种实现方式
  • William on 新浪微博API for MOAI
  • Benny Chen on 新浪微博API for MOAI
  • your man on 新浪微博API for MOAI
  • 你家男人 on 稍后继续
  • 逍遥 on 关于对std::vector的遍历
  • papa on Unity Developer ++
  • T客网 ︱ Techpot » Blog Archive » iOS开发与OpenGL ES相关问题整理(1) on iOS开发与OpenGL ES相关问题整理(1)

Tags

2d 3D 3dsmax 3ds max air Apply architecture Asia tour barca Beijing bilbao binary search blocked bob boost bruce springsteen C++ capo CGContextDrawImage Champions League Change DLL DX10 eval exporter flash framework frustum culling game game engine iniesta ios linux lua Moai opengles pacman plug-in plugin 北京 导出插件 崩溃 巴萨 游戏引擎 踢球
© Copyright 2026 - A Game Developer
Infinity Theme by DesignCoral / WordPress