From 12bd01c56710d957e28bea41aab9f9b98182e72b Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 12 May 2014 16:13:32 -0300 Subject: [PATCH] added comments to several functions --- lvm.c | 148 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 55 deletions(-) diff --git a/lvm.c b/lvm.c index 3854c90a..12e2b090 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.205 2014/05/01 18:18:06 roberto Exp roberto $ +** $Id: lvm.c,v 2.206 2014/05/09 14:20:52 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -56,7 +56,8 @@ static int tofloat (const TValue *obj, lua_Number *n) { /* -** Try to convert a value to a float +** Try to convert a value to a float. Check 'isinteger' first, because +** in general the float case is already handled by the macro 'tonumber'. */ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { TValue v; @@ -69,7 +70,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { *n = fltvalue(obj); return 1; } - else if (ttisstring(obj) && + else if (ttisstring(obj) && /* string convertible to number? */ luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { obj = &v; goto again; /* convert result from 'luaO_str2num' to a float */ @@ -178,8 +179,12 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, } +/* +** Main function for table access (invoking metamethods if needed). +** Compute 'val = t[key]' +*/ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; + int loop; /* counter to avoid infinite loops */ for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ @@ -187,32 +192,36 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { const TValue *res = luaH_get(h, key); /* do a primitive get */ if (!ttisnil(res) || /* result is not nil? */ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ - setobj2s(L, val, res); + setobj2s(L, val, res); /* result is the raw get */ return; } - /* else will try the tag method */ + /* else will try metamethod */ } else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { + luaG_typeerror(L, t, "index"); /* no metamethod */ + if (ttisfunction(tm)) { /* metamethod is a function */ luaT_callTM(L, tm, t, key, val, 1); return; } - t = tm; /* else repeat with 'tm' */ + t = tm; /* else repeat access over 'tm' */ } luaG_runerror(L, "gettable chain too long; possible loop"); } +/* +** Main function for table assignment (invoking metamethods if needed). +** Compute 't[key] = val' +*/ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; + int loop; /* counter to avoid infinite loops */ for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ Table *h = hvalue(t); TValue *oldval = cast(TValue *, luaH_get(h, key)); /* if previous value is not nil, there must be a previous entry - in the table; moreover, a metamethod has no relevance */ + in the table; a metamethod has no relevance */ if (!ttisnil(oldval) || /* previous value is nil; must check the metamethod */ ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && @@ -232,32 +241,40 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { else /* not a table; check metamethod */ if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) luaG_typeerror(L, t, "index"); - /* there is a metamethod */ + /* try the metamethod */ if (ttisfunction(tm)) { luaT_callTM(L, tm, t, key, val, 0); return; } - t = tm; /* else repeat with 'tm' */ + t = tm; /* else repeat assginment over 'tm' */ } luaG_runerror(L, "settable chain too long; possible loop"); } +/* +** Compare two strings 'ls' x 'rs', returning an integer smaller-equal- +** -larger than zero if 'ls' is smaller-equal-larger than 'rs'. +** The code is a little tricky because it allows '\0' in the strings +** and it uses 'strcoll' (to respect locales) for each segments +** of the strings. +*/ static int l_strcmp (const TString *ls, const TString *rs) { const char *l = getstr(ls); size_t ll = ls->tsv.len; const char *r = getstr(rs); size_t lr = rs->tsv.len; - for (;;) { + for (;;) { /* for each segment */ int temp = strcoll(l, r); - if (temp != 0) return temp; - else { /* strings are equal up to a `\0' */ + if (temp != 0) /* not equal? */ + return temp; /* done */ + else { /* strings are equal up to a '\0' */ size_t len = strlen(l); /* index of first `\0' in both strings */ - if (len == lr) /* r is finished? */ - return (len == ll) ? 0 : 1; - else if (len == ll) /* l is finished? */ - return -1; /* l is smaller than r (because r is not finished) */ - /* both strings longer than `len'; go on comparing (after the `\0') */ + if (len == lr) /* 'rs' is finished? */ + return (len == ll) ? 0 : 1; /* check 'ls' */ + else if (len == ll) /* 'ls' is finished? */ + return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */ + /* both strings longer than `len'; go on comparing after the '\0' */ len++; l += len; ll -= len; r += len; lr -= len; } @@ -265,29 +282,35 @@ static int l_strcmp (const TString *ls, const TString *rs) { } +/* +** Main operation less than; return 'l < r'. +*/ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int res; lua_Number nl, nr; - if (ttisinteger(l) && ttisinteger(r)) + if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */ return (ivalue(l) < ivalue(r)); - else if (tofloat(l, &nl) && tofloat(r, &nr)) + else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */ return luai_numlt(nl, nr); - else if (ttisstring(l) && ttisstring(r)) + else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; - else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) - luaG_ordererror(L, l, r); + else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ + luaG_ordererror(L, l, r); /* error */ return res; } +/* +** Main operation less than or equal to; return 'l <= r'. +*/ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { int res; lua_Number nl, nr; - if (ttisinteger(l) && ttisinteger(r)) + if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */ return (ivalue(l) <= ivalue(r)); - else if (tofloat(l, &nl) && tofloat(r, &nr)) + else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */ return luai_numle(nl, nr); - else if (ttisstring(l) && ttisstring(r)) + else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ return res; @@ -298,15 +321,16 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { /* -** equality of Lua values. L == NULL means raw equality (no metamethods) +** Main operation for equality of Lua values; return 't1 == t2'. +** L == NULL means raw equality (no metamethods) */ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { const TValue *tm; - if (ttype(t1) != ttype(t2)) { + if (ttype(t1) != ttype(t2)) { /* not the same variant? */ if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) return 0; /* only numbers can be equal with different variants */ else { /* two numbers with different variants */ - lua_Number n1, n2; + lua_Number n1, n2; /* compare them as floats */ lua_assert(ttisnumber(t1) && ttisnumber(t2)); cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2)); return luai_numeq(n1, n2); @@ -343,8 +367,13 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { } +/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) +/* +** Main operation for concatenation: concat 'total' values in the stack, +** from 'L->top - total' up to 'L->top - 1'. +*/ void luaV_concat (lua_State *L, int total) { lua_assert(total >= 2); do { @@ -372,12 +401,12 @@ void luaV_concat (lua_State *L, int total) { buffer = luaZ_openspace(L, &G(L)->buff, tl); tl = 0; n = i; - do { /* concat all strings */ + do { /* copy all strings to buffer */ size_t l = tsvalue(top-i)->len; memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); tl += l; } while (--i > 0); - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); /* create result */ } total -= n-1; /* got 'n' strings to create 1 new */ L->top -= n-1; /* popped 'n' strings and pushed one */ @@ -385,6 +414,9 @@ void luaV_concat (lua_State *L, int total) { } +/* +** Main operation 'ra' = #rb'. +*/ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { const TValue *tm; switch (ttnov(rb)) { @@ -410,15 +442,18 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { } -lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { - if (l_castS2U(y) + 1u <= 1u) { /* special cases: -1 or 0 */ - if (y == 0) +/* +** Integer division; return 'm // n'. +*/ +lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { + if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ + if (n == 0) luaG_runerror(L, "attempt to divide by zero"); - return intop(-, 0, x); /* y==-1; avoid overflow with 0x80000...//-1 */ + return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ } else { - lua_Integer d = x / y; /* perform division */ - if ((x ^ y) >= 0 || x % y == 0) /* same signal or no rest? */ + lua_Integer d = m / n; /* perform division */ + if ((m ^ n) >= 0 || m % n == 0) /* same signal or no rest? */ return d; else return d - 1; /* correct 'div' for negative case */ @@ -426,33 +461,36 @@ lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { } -lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { - if (l_castS2U(y) + 1u <= 1u) { /* special cases: -1 or 0 */ - if (y == 0) +/* +** Integer modulus; return 'm % n'. +*/ +lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { + if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ + if (n == 0) luaG_runerror(L, "attempt to perform 'n%%0'"); - return 0; /* y==-1; avoid overflow with 0x80000...%-1 */ + return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ } else { - lua_Integer r = x % y; - if (r == 0 || (x ^ y) >= 0) + lua_Integer r = m % n; + if (r == 0 || (m ^ n) >= 0) return r; else - return r + y; /* correct 'mod' for negative case */ + return r + n; /* correct 'mod' for negative case */ } } -lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { - lua_assert(y >= 0); - if (y == 0) - return 1; /* x^0 == 1 */ +lua_Integer luaV_pow (lua_Integer m, lua_Integer n) { + lua_assert(n >= 0); + if (n == 0) + return 1; /* m^0 == 1 */ else { lua_Integer r = 1; - for (; y > 1; y >>= 1) { - if (y & 1) r = intop(*, r, x); - x = intop(*, x, x); + for (; n > 1; n >>= 1) { + if (n & 1) r = intop(*, r, m); + m = intop(*, m, m); } - r = intop(*, r, x); + r = intop(*, r, m); return r; } }