From 7dfa4cd655118faf164427356609fec31906dac2 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 14 Apr 2010 12:13:48 -0300 Subject: [PATCH] first implementation of light C functions --- lapi.c | 68 +++++++++++++++++++++++++++++++++---------------------- ldebug.c | 32 ++++++++++++++------------ ldo.c | 54 ++++++++++++++++++++++++------------------- lobject.c | 4 +++- lobject.h | 39 +++++++++++++++++++++++-------- lstate.h | 3 +-- ltable.c | 4 +++- ltests.c | 9 +++++--- ltm.c | 4 ++-- ltm.h | 5 ++-- lvm.c | 7 +++--- 11 files changed, 141 insertions(+), 88 deletions(-) diff --git a/lapi.c b/lapi.c index 0ed2734d..805eedef 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.119 2010/04/02 15:19:19 roberto Exp roberto $ +** $Id: lapi.c,v 2.120 2010/04/05 14:21:38 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -54,12 +54,16 @@ static TValue *index2addr (lua_State *L, int idx) { else if (idx == LUA_REGISTRYINDEX) return &G(L)->l_registry; else { /* upvalues */ - Closure *func = curr_func(L); idx = LUA_REGISTRYINDEX - idx; api_check(L, idx <= UCHAR_MAX + 1, "upvalue index too large"); - return (idx <= func->c.nupvalues) - ? &func->c.upvalue[idx-1] - : cast(TValue *, luaO_nilobject); + if (ttiscfp(ci->func)) /* C-function pointer? */ + return cast(TValue *, luaO_nilobject); /* it has no upvalues */ + else { + Closure *func = clvalue(ci->func); + return (idx <= func->c.nupvalues) + ? &func->c.upvalue[idx-1] + : cast(TValue *, luaO_nilobject); + } } } @@ -181,8 +185,10 @@ static void moveto (lua_State *L, TValue *fr, int idx) { TValue *to = index2addr(L, idx); api_checkvalidindex(L, to); setobj(L, to, fr); - if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ - luaC_barrier(L, curr_func(L), fr); + if (idx < LUA_REGISTRYINDEX) { /* function upvalue? */ + lua_assert(ttisclosure(L->ci->func)); + luaC_barrier(L, clvalue(L->ci->func), fr); + } /* LUA_REGISTRYINDEX does not need gc barrier (collector revisits it before finishing collection) */ } @@ -223,19 +229,19 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { LUA_API int lua_type (lua_State *L, int idx) { StkId o = index2addr(L, idx); - return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); + return (o == luaO_nilobject) ? LUA_TNONE : ttypenv(o); } LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); - return typename(t); + return ttypename(t); } LUA_API int lua_iscfunction (lua_State *L, int idx) { StkId o = index2addr(L, idx); - return iscfunction(o); + return (ttiscfp(o) || (ttisclosure(o) && clvalue(o)->c.isC)); } @@ -361,7 +367,10 @@ LUA_API size_t lua_rawlen (lua_State *L, int idx) { LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { StkId o = index2addr(L, idx); - return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; + if (ttiscfp(o)) return fvalue(o); + else if (ttisclosure(o) && clvalue(o)->c.isC) + return clvalue(o)->c.f; + else return NULL; /* not a C function */ } @@ -386,6 +395,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { switch (ttype(o)) { case LUA_TTABLE: return hvalue(o); case LUA_TFUNCTION: return clvalue(o); + case LUA_TCFP: return cast(void *, cast(size_t, fvalue(o))); case LUA_TTHREAD: return thvalue(o); case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: @@ -480,18 +490,22 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - Closure *cl; lua_lock(L); - api_checknelems(L, n); - api_check(L, n <= UCHAR_MAX, "upvalue index too large"); - luaC_checkGC(L); - cl = luaF_newCclosure(L, n); - cl->c.f = fn; - L->top -= n; - while (n--) - setobj2n(L, &cl->c.upvalue[n], L->top+n); - setclvalue(L, L->top, cl); - lua_assert(iswhite(obj2gco(cl))); + if (n == 0) { + setfvalue(L->top, fn); + } + else { + Closure *cl; + api_checknelems(L, n); + api_check(L, n <= UCHAR_MAX, "upvalue index too large"); + luaC_checkGC(L); + cl = luaF_newCclosure(L, n); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(L, &cl->c.upvalue[n], L->top + n); + setclvalue(L, L->top, cl); + } api_incr_top(L); lua_unlock(L); } @@ -598,7 +612,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { mt = uvalue(obj)->metatable; break; default: - mt = G(L)->mt[ttype(obj)]; + mt = G(L)->mt[ttypenv(obj)]; break; } if (mt == NULL) @@ -713,7 +727,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { break; } default: { - G(L)->mt[ttype(obj)] = mt; + G(L)->mt[ttypenv(obj)] = mt; break; } } @@ -1063,7 +1077,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { static const char *aux_upvalue (StkId fi, int n, TValue **val) { Closure *f; - if (!ttisfunction(fi)) return NULL; + if (!ttisclosure(fi)) return NULL; f = clvalue(fi); if (f->c.isC) { if (!(1 <= n && n <= f->c.nupvalues)) return NULL; @@ -1115,7 +1129,7 @@ static UpVal **getupvalref (lua_State *L, int fidx, int n, Closure **pf) { Closure *f; Proto *p; StkId fi = index2addr(L, fidx); - api_check(L, ttisfunction(fi), "function expected"); + api_check(L, ttisclosure(fi), "Lua function expected"); f = clvalue(fi); api_check(L, !f->c.isC, "Lua function expected"); p = f->l.p; @@ -1128,7 +1142,7 @@ static UpVal **getupvalref (lua_State *L, int fidx, int n, Closure **pf) { LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { Closure *f; StkId fi = index2addr(L, fidx); - api_check(L, ttisfunction(fi), "function expected"); + api_check(L, ttisclosure(fi), "function expected"); f = clvalue(fi); if (f->c.isC) { api_check(L, 1 <= n && n <= f->c.nupvalues, "invalid upvalue index"); diff --git a/ldebug.c b/ldebug.c index 03c86762..9b3e2d1c 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.68 2010/04/05 16:26:37 roberto Exp roberto $ +** $Id: ldebug.c,v 2.69 2010/04/08 17:06:33 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -144,7 +144,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { static void funcinfo (lua_Debug *ar, Closure *cl) { - if (cl->c.isC) { + if (cl == NULL || cl->c.isC) { ar->source = "=[C]"; ar->linedefined = -1; ar->lastlinedefined = -1; @@ -191,8 +191,8 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 'u': { - ar->nups = f->c.nupvalues; - if (f->c.isC) { + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (f == NULL || f->c.isC) { ar->isvararg = 1; ar->nparams = 0; } @@ -226,28 +226,30 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { int status; - Closure *f = NULL; - CallInfo *ci = NULL; + Closure *cl; + CallInfo *ci; + StkId func; lua_lock(L); if (*what == '>') { - StkId func = L->top - 1; + ci = NULL; + func = L->top - 1; luai_apicheck(L, ttisfunction(func)); what++; /* skip the '>' */ - f = clvalue(func); L->top--; /* pop function */ } else { ci = ar->i_ci; + func = ci->func; lua_assert(ttisfunction(ci->func)); - f = clvalue(ci->func); } - status = auxgetinfo(L, what, ar, f, ci); + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); if (strchr(what, 'f')) { - setclvalue(L, L->top, f); + setobjs2s(L, L->top, func); incr_top(L); } if (strchr(what, 'L')) - collectvalidlines(L, f); + collectvalidlines(L, cl); lua_unlock(L); return status; } @@ -439,7 +441,7 @@ static const char *getupvalname (CallInfo *ci, const TValue *o, void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { CallInfo *ci = L->ci; const char *name = NULL; - const char *t = typename(ttype(o)); + const char *t = objtypename(o); const char *kind = NULL; if (isLua(ci)) { kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ @@ -470,8 +472,8 @@ void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = typename(ttype(p1)); - const char *t2 = typename(ttype(p2)); + const char *t1 = objtypename(p1); + const char *t2 = objtypename(p2); if (t1 == t2) luaG_runerror(L, "attempt to compare two %s values", t1); else diff --git a/ldo.c b/ldo.c index 400afa0f..56813c04 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.82 2010/03/26 20:58:11 roberto Exp roberto $ +** $Id: ldo.c,v 2.83 2010/04/08 17:16:46 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -293,18 +293,43 @@ static StkId tryfuncTM (lua_State *L, StkId func) { ** returns true if function has been executed (C function) */ int luaD_precall (lua_State *L, StkId func, int nresults) { - LClosure *cl; + Closure *cl; + lua_CFunction f; ptrdiff_t funcr; if (!ttisfunction(func)) /* `func' is not a function? */ func = tryfuncTM(L, func); /* check the `function' tag method */ funcr = savestack(L, func); - cl = &clvalue(func)->l; L->ci->nresults = nresults; - if (!cl->isC) { /* Lua function? prepare its call */ + if (ttiscfp(func)) { /* C function pointer? */ + f = fvalue(func); /* get it */ + goto isCfunc; /* go to call it */ + } + cl = clvalue(func); + if (cl->c.isC) { /* C closure? */ + CallInfo *ci; + int n; + f = cl->c.f; + isCfunc: /* call C function 'f' */ + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = next_ci(L); /* now 'enter' new function */ + ci->func = restorestack(L, funcr); + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = 0; + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, L->top - n); + return 1; + } + else { /* Lua function: prepare its call */ CallInfo *ci; int nparams, nargs; StkId base; - Proto *p = cl->p; + Proto *p = cl->l.p; luaD_checkstack(L, p->maxstacksize); func = restorestack(L, funcr); nargs = cast_int(L->top - func) - 1; /* number of real arguments */ @@ -327,24 +352,6 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { callhook(L, ci); return 0; } - else { /* if is a C function, call it */ - CallInfo *ci; - int n; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci = next_ci(L); /* now 'enter' new function */ - ci->func = restorestack(L, funcr); - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->callstatus = 0; - if (L->hookmask & LUA_MASKCALL) - luaD_hook(L, LUA_HOOKCALL, -1); - lua_unlock(L); - n = (*curr_func(L)->c.f)(L); /* do the actual call */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, L->top - n); - return 1; - } } @@ -526,6 +533,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) { luai_userstateresume(L, nargs); ++G(L)->nCcalls; /* count resume */ L->nny = 0; /* allow yields */ + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); status = luaD_rawrunprotected(L, resume, L->top - nargs); if (status == -1) /* error calling 'lua_resume'? */ status = LUA_ERRRUN; diff --git a/lobject.c b/lobject.c index 3c87da1c..548c1d05 100644 --- a/lobject.c +++ b/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.36 2010/04/02 15:30:27 roberto Exp roberto $ +** $Id: lobject.c,v 2.37 2010/04/05 16:26:37 roberto Exp roberto $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -83,6 +83,8 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) { return pvalue(t1) == pvalue(t2); case LUA_TSTRING: return rawtsvalue(t1) == rawtsvalue(t2); + case LUA_TCFP: + return fvalue(t1) == fvalue(t2); default: lua_assert(iscollectable(t1)); return gcvalue(t1) == gcvalue(t2); diff --git a/lobject.h b/lobject.h index ce8e9e26..f093b3cb 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.36 2010/03/26 20:58:11 roberto Exp roberto $ +** $Id: lobject.h,v 2.37 2010/04/12 16:07:06 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -24,6 +24,12 @@ #define LUA_TDEADKEY (LUA_NUMTAGS+2) +/* +** Variant tag for C-function pointers (negative to be considered +** non collectable by 'iscollectable') +*/ +#define LUA_TCFP (~0x0F | LUA_TFUNCTION) + /* ** Union of all collectable objects */ @@ -54,6 +60,7 @@ typedef union { void *p; lua_Number n; int b; + lua_CFunction f; } Value; @@ -73,12 +80,26 @@ typedef struct lua_TValue { #define NILCONSTANT {NULL}, LUA_TNIL +/* +** type tag of a TValue +*/ +#define ttype(o) ((o)->tt_) + + +/* +** type tag of a TValue with no variants +*/ +#define ttypenv(o) (ttype(o) & 0x0F) + + /* Macros to test type */ #define ttisnil(o) (ttype(o) == LUA_TNIL) #define ttisnumber(o) (ttype(o) == LUA_TNUMBER) #define ttisstring(o) (ttype(o) == LUA_TSTRING) #define ttistable(o) (ttype(o) == LUA_TTABLE) -#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +#define ttisfunction(o) (ttypenv(o) == LUA_TFUNCTION) +#define ttisclosure(o) (ttype(o) == LUA_TFUNCTION) +#define ttiscfp(o) (ttype(o) == LUA_TCFP) #define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) #define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) #define ttisthread(o) (ttype(o) == LUA_TTHREAD) @@ -86,7 +107,6 @@ typedef struct lua_TValue { #define ttisdeadkey(o) (ttype(o) == LUA_TDEADKEY) /* Macros to access values */ -#define ttype(o) ((o)->tt_) #define gcvalue(o) check_exp(iscollectable(o), (o)->value_.gc) #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value_.p) #define nvalue(o) check_exp(ttisnumber(o), (o)->value_.n) @@ -94,16 +114,15 @@ typedef struct lua_TValue { #define tsvalue(o) (&rawtsvalue(o)->tsv) #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value_.gc->u) #define uvalue(o) (&rawuvalue(o)->uv) -#define clvalue(o) check_exp(ttisfunction(o), &(o)->value_.gc->cl) +#define clvalue(o) check_exp(ttisclosure(o), &(o)->value_.gc->cl) +#define fvalue(o) check_exp(ttiscfp(o), (o)->value_.f) #define hvalue(o) check_exp(ttistable(o), &(o)->value_.gc->h) #define bvalue(o) check_exp(ttisboolean(o), (o)->value_.b) #define thvalue(o) check_exp(ttisthread(o), &(o)->value_.gc->th) #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) -/* -** for internal debug only -*/ + #define iscollectable(o) (ttype(o) >= LUA_TSTRING) #define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) @@ -120,6 +139,9 @@ typedef struct lua_TValue { #define setnvalue(obj,x) \ { TValue *i_o=(obj); i_o->value_.n=(x); i_o->tt_=LUA_TNUMBER; } +#define setfvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value_.f=(x); i_o->tt_=LUA_TCFP; } + #define changenvalue(obj,x) \ ( lua_assert((obj)->tt_==LUA_TNUMBER), (obj)->value_.n=(x) ) @@ -313,8 +335,7 @@ typedef union Closure { } Closure; -#define iscfunction(o) (ttisfunction(o) && clvalue(o)->c.isC) -#define isLfunction(o) (ttisfunction(o) && !clvalue(o)->c.isC) +#define isLfunction(o) (ttisclosure(o) && !clvalue(o)->c.isC) #define getproto(o) (clvalue(o)->l.p) diff --git a/lstate.h b/lstate.h index fc496b12..734898d0 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.61 2010/04/08 17:16:46 roberto Exp roberto $ +** $Id: lstate.h,v 2.62 2010/04/12 16:07:06 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -105,7 +105,6 @@ typedef struct CallInfo { #define CIST_TAIL (1<<6) /* call was tail called */ -#define curr_func(L) (clvalue(L->ci->func)) #define ci_func(ci) (clvalue((ci)->func)) #define isLua(ci) ((ci)->callstatus & CIST_LUA) diff --git a/ltable.c b/ltable.c index c7a7606b..7eb1f4a9 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.47 2009/12/17 15:46:44 roberto Exp roberto $ +** $Id: ltable.c,v 2.48 2010/04/05 16:26:37 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -109,6 +109,8 @@ static Node *mainposition (const Table *t, const TValue *key) { return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: return hashpointer(t, pvalue(key)); + case LUA_TCFP: + return hashpointer(t, fvalue(key)); default: return hashpointer(t, gcvalue(key)); } diff --git a/ltests.c b/ltests.c index b8276ce5..58fcb5b9 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.92 2010/04/12 12:42:07 roberto Exp roberto $ +** $Id: ltests.c,v 2.93 2010/04/12 16:07:39 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -191,7 +191,7 @@ static void printobj (global_State *g, GCObject *o) { GCObject *p; for (p = g->allgc; p != o && p != NULL; p = gch(p)->next) i++; if (p == NULL) i = -1; - printf("%d:%s(%p)-%c(%02X)", i, typename(gch(o)->tt), (void *)o, + printf("%d:%s(%p)-%c(%02X)", i, ttypename(gch(o)->tt), (void *)o, isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); } @@ -519,7 +519,7 @@ static int mem_query (lua_State *L) { const char *t = luaL_checkstring(L, 1); int i; for (i = LUA_NUMTAGS - 1; i >= 0; i--) { - if (strcmp(t, typename(i)) == 0) { + if (strcmp(t, ttypename(i)) == 0) { lua_pushinteger(L, l_memcontrol.objcount[i]); return 1; } @@ -944,6 +944,9 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) { else if EQ("tonumber") { lua_pushnumber(L1, lua_tonumber(L1, getindex)); } + else if EQ("topointer") { + lua_pushlightuserdata(L1, cast(void *, lua_topointer(L1, getindex))); + } else if EQ("tostring") { const char *s = lua_tostring(L1, getindex); const char *s1 = lua_pushstring(L1, s); diff --git a/ltm.c b/ltm.c index b859164b..1d1e5d1a 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.10 2009/11/19 19:06:52 roberto Exp roberto $ +** $Id: ltm.c,v 2.11 2010/01/13 16:18:25 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -70,7 +70,7 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { mt = uvalue(o)->metatable; break; default: - mt = G(L)->mt[ttype(o)]; + mt = G(L)->mt[ttypenv(o)]; } return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); } diff --git a/ltm.h b/ltm.h index adb1b2e3..be079b30 100644 --- a/ltm.h +++ b/ltm.h @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 2.8 2009/11/19 19:06:52 roberto Exp roberto $ +** $Id: ltm.h,v 2.9 2010/01/13 16:18:25 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -43,7 +43,8 @@ typedef enum { #define fasttm(l,et,e) gfasttm(G(l), et, e) -#define typename(x) luaT_typenames_[(x) + 1] +#define ttypename(x) luaT_typenames_[(x) + 1] +#define objtypename(x) ttypename(ttypenv(x)) LUAI_DDEC const char *const luaT_typenames_[]; diff --git a/lvm.c b/lvm.c index d9d63f35..41be38a7 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.109 2010/04/02 15:39:07 roberto Exp roberto $ +** $Id: lvm.c,v 2.110 2010/04/05 16:26:37 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -218,7 +218,7 @@ static int l_strcmp (const TString *ls, const TString *rs) { int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int res; - if (ttype(l) != ttype(r)) + if (ttypenv(l) != ttypenv(r)) return luaG_ordererror(L, l, r); else if (ttisnumber(l)) return luai_numlt(L, nvalue(l), nvalue(r)); @@ -232,7 +232,7 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { int res; - if (ttype(l) != ttype(r)) + if (ttypenv(l) != ttypenv(r)) return luaG_ordererror(L, l, r); else if (ttisnumber(l)) return luai_numle(L, nvalue(l), nvalue(r)); @@ -254,6 +254,7 @@ int luaV_equalval_ (lua_State *L, const TValue *t1, const TValue *t2) { case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TCFP: return fvalue(t1) == fvalue(t2); case LUA_TSTRING: return eqstr(rawtsvalue(t1), rawtsvalue(t2)); case LUA_TUSERDATA: { if (uvalue(t1) == uvalue(t2)) return 1;