11/*
2- ** $Id: lvm.c,v 2.237 2015/03/07 19:30:16 roberto Exp roberto $
2+ ** $Id: lvm.c,v 2.238 2015/03/30 15:45:01 roberto Exp roberto $
33** Lua virtual machine
44** See Copyright Notice in lua.h
55*/
@@ -262,7 +262,12 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
262262
263263
264264/*
265- ** Main operation less than or equal to; return 'l <= r'.
265+ ** Main operation less than or equal to; return 'l <= r'. If it needs
266+ ** a metamethod and there is no '__le', try '__lt', based on
267+ ** l <= r iff !(r < l) (assuming a total order). If the metamethod
268+ ** yields during this substitution, the continuation has to know
269+ ** about it (to negate the result of r<l); bit CIST_LEQ in the call
270+ ** status keeps that information.
266271*/
267272int luaV_lessequal (lua_State * L , const TValue * l , const TValue * r ) {
268273 int res ;
@@ -273,11 +278,16 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
273278 return luai_numle (nl , nr );
274279 else if (ttisstring (l ) && ttisstring (r )) /* both are strings? */
275280 return l_strcmp (tsvalue (l ), tsvalue (r )) <= 0 ;
276- else if ((res = luaT_callorderTM (L , l , r , TM_LE )) >= 0 ) /* first try 'le' */
281+ else if ((res = luaT_callorderTM (L , l , r , TM_LE )) >= 0 ) /* try 'le' */
277282 return res ;
278- else if ((res = luaT_callorderTM (L , r , l , TM_LT )) < 0 ) /* else try 'lt' */
279- luaG_ordererror (L , l , r );
280- return !res ;
283+ else { /* try 'lt': */
284+ L -> ci -> callstatus |= CIST_LEQ ; /* mark it is doing 'lt' for 'le' */
285+ res = luaT_callorderTM (L , r , l , TM_LT );
286+ L -> ci -> callstatus ^= CIST_LEQ ; /* clear mark */
287+ if (res < 0 )
288+ luaG_ordererror (L , l , r );
289+ return !res ; /* result is negated */
290+ }
281291}
282292
283293
@@ -542,11 +552,11 @@ void luaV_finishOp (lua_State *L) {
542552 case OP_LE : case OP_LT : case OP_EQ : {
543553 int res = !l_isfalse (L -> top - 1 );
544554 L -> top -- ;
545- /* metamethod should not be called when operand is K */
546- lua_assert (! ISK ( GETARG_B ( inst )) );
547- if ( op == OP_LE && /* "<=" using "<" instead? */
548- ttisnil ( luaT_gettmbyobj ( L , base + GETARG_B ( inst ), TM_LE )))
549- res = ! res ; /* invert result */
555+ if ( ci -> callstatus & CIST_LEQ ) { /* "<=" using "<" instead? */
556+ lua_assert (op == OP_LE );
557+ ci -> callstatus ^= CIST_LEQ ; /* clear mark */
558+ res = ! res ; /* negate result */
559+ }
550560 lua_assert (GET_OPCODE (* ci -> u .l .savedpc ) == OP_JMP );
551561 if (res != GETARG_A (inst )) /* condition failed? */
552562 ci -> u .l .savedpc ++ ; /* skip jump instruction */
0 commit comments