--- lua-5.3.1/src/ltm.h 2014年10月25日 12:50:46.000000000 +0100 +++ lua-5.3.1jh/src/ltm.h 2015年07月23日 21:35:58.000000000 +0100 @@ -37,12 +37,15 @@ TM_UNM, TM_BNOT, TM_LT, TM_LE, TM_CONCAT, TM_CALL, +#if defined(JH_LUA_ITER) + TM_ITER, +#endif TM_N /* number of elements in the enum */ } TMS; --- lua-5.3.1/src/ltm.c 2015年03月30日 16:42:26.000000000 +0100 +++ lua-5.3.1jh/src/ltm.c 2015年07月23日 21:37:49.000000000 +0100 @@ -40,12 +40,15 @@ "__gc", "__mode", "__len", "__eq", "__add", "__sub", "__mul", "__mod", "__pow", "__div", "__idiv", "__band", "__bor", "__bxor", "__shl", "__shr", "__unm", "__bnot", "__lt", "__le", "__concat", "__call" +#if defined(JH_LUA_ITER) + ,"__iter" +#endif }; --- lua-5.3.1/src/lvm.c 2015年06月09日 16:53:34.000000000 +0100 +++ lua-5.3.1jh/src/lvm.c 2015年09月22日 12:35:58.000000000 +0100 @@ -683,13 +683,23 @@ case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: break; default: lua_assert(0); } } +#if defined(JH_LUA_ITER) +static int jhiter_next(lua_State *L) { + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} +#endif /* ** {================================================================== ** Function 'luaV_execute': main interpreter loop ** =================================================================== @@ -1185,12 +1195,52 @@ luaG_runerror(L, "'for' initial value must be a number"); setfltvalue(init, luai_numsub(L, ninit, nstep)); } ci->u.l.savedpc += GETARG_sBx(i); vmbreak; } +#if defined(JH_LUA_ITER) + vmcase(OP_TFORCALL) { + StkId cb = ra + 3; /* call base */ + /* NEW CODE - Here to NEW CODE ENDS marker - have to duplicate the rest due to use of pre-processor macro */ + if ((!ttisfunction(ra)) && (ttisnil(ra + 1)) && (ttisnil(ra + 2))) { + /* Intervene before first iteration if sole iteration value is not an iterator function */ + const TValue *tm = luaT_gettmbyobj(L, ra, TM_ITER); + if (ttisnil(tm)) { + if (ttistable(ra)) { + /* Table with no metamethod: default to 'next' */ + setobjs2s(L, ra + 1, ra); + setfvalue(ra, jhiter_next); + } + } + else { /* Metamethod found: call it to replace the iteration values */ + setobjs2s(L, cb, tm); + setobjs2s(L, cb + 1, ra); + L->top = cb + 2; /* metamethod + object for method call */ + Protect(luaD_call(L, cb, 3, 1)); + L->top = L->ci->top; + ra = RA(i); + setobj2s(L, ra + 2, cb + 2); + setobj2s(L, ra + 1, cb + 1); + setobj2s(L, ra, cb); + L->top = ra + 3; + } + } + /* NEW CODE ENDS */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb + 3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i), 1)); + L->top = ci->top; + i = *(ci->u.l.savedpc++); /* go to next instruction */ + ra = RA(i); + lua_assert(GET_OPCODE(i) == OP_TFORLOOP); + goto l_tforloop; + } +#else vmcase(OP_TFORCALL) { StkId cb = ra + 3; /* call base */ setobjs2s(L, cb+2, ra+2); setobjs2s(L, cb+1, ra+1); setobjs2s(L, cb, ra); L->top = cb + 3; /* func. + 2 args (state and index) */ @@ -1198,12 +1248,13 @@ L->top = ci->top; i = *(ci->u.l.savedpc++); /* go to next instruction */ ra = RA(i); lua_assert(GET_OPCODE(i) == OP_TFORLOOP); goto l_tforloop; } +#endif vmcase(OP_TFORLOOP) { l_tforloop: if (!ttisnil(ra + 1)) { /* continue loop? */ setobjs2s(L, ra, ra + 1); /* save control variable */ ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ } --- lua-5.3.1/doc/manual.html 2015年06月10日 22:31:16.000000000 +0100 +++ lua-5.3.1jh/doc/manual.html 2015年09月22日 17:24:24.000000000 +0100 @@ -21,12 +21,20 @@ Copyright © 2015 Lua.org, PUC-Rio. Freely available under the terms of the Lua license. +

+[JH-LUA-ITER]: Self-iterating Objects Powerpatch (see §2.4, +§3.3.5, §8).

contents · index · other versions @@ -645,12 +653,23 @@ Lua does not perform the primitive assignment. (If necessary, the metamethod itself can call rawset to do the assignment.) +

+

  • "iter": [JH-LUA-ITER] The iteration operation +for items in explist do. This event happens when the first and only non-nil +item in explist is not a function (or closure). If present, the +metamethod is called with the item as its only argument. The return values replace +the explist and are used to perform the iteration in the usual +way (see §3.3.5). Therefore, the metamethod should have the +same signature as the pairs global function. +
  • + +

  • "call": The call operation func(args). This event happens when Lua tries to call a non-function value (that is, func is not a function). The metamethod is looked up in func. @@ -1663,13 +1682,23 @@ stopping when this new value is nil. The generic for loop has the following syntax:
     stat ::= for namelist in explist do block end
     namelist ::= Name {‘,’ Name}
    -

    + + +

    +[JH-LUA-ITER]: As an alternative to an interator function, a table or userdata +may be specified as the first and only expression in explist. In this case a metamethod +__iter, if present, is called with the table or userdata as the only parameter. The first three +return parameters replace the explist for the iteration. In the case of a table, if a +metamethod is not present an iteration method functionally equavalent to pairs is used by default. + +

    + A for statement like

     for var_1, ···, var_n in explist do block end
     

    is equivalent to the code: @@ -10697,12 +10732,25 @@ Use their equivalent over lua_Integer with a type cast (or, when possible, use lua_Integer in your code).

  • +

    8.4 – Incompatibilities with standard Lua

    + + +

    9 – The Complete Syntax of Lua

    AltStyle によって変換されたページ (->オリジナル) /