diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-05-12 16:13:32 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-05-12 16:13:32 -0300 |
| commit | 12bd01c56710d957e28bea41aab9f9b98182e72b (patch) | |
| tree | 05027217ff06c46d7d3632db922c624ca9a7fdae | |
| parent | 626124d2d8ae582c3444a9e0e11b09f31dc098ff (diff) | |
| download | lua-12bd01c56710d957e28bea41aab9f9b98182e72b.tar.gz lua-12bd01c56710d957e28bea41aab9f9b98182e72b.tar.bz2 lua-12bd01c56710d957e28bea41aab9f9b98182e72b.zip | |
added comments to several functions
| -rw-r--r-- | lvm.c | 148 |
1 files changed, 93 insertions, 55 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.205 2014/05/01 18:18:06 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.206 2014/05/09 14:20:52 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -56,7 +56,8 @@ static int tofloat (const TValue *obj, lua_Number *n) { | |||
| 56 | 56 | ||
| 57 | 57 | ||
| 58 | /* | 58 | /* |
| 59 | ** Try to convert a value to a float | 59 | ** Try to convert a value to a float. Check 'isinteger' first, because |
| 60 | ** in general the float case is already handled by the macro 'tonumber'. | ||
| 60 | */ | 61 | */ |
| 61 | int luaV_tonumber_ (const TValue *obj, lua_Number *n) { | 62 | int luaV_tonumber_ (const TValue *obj, lua_Number *n) { |
| 62 | TValue v; | 63 | TValue v; |
| @@ -69,7 +70,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { | |||
| 69 | *n = fltvalue(obj); | 70 | *n = fltvalue(obj); |
| 70 | return 1; | 71 | return 1; |
| 71 | } | 72 | } |
| 72 | else if (ttisstring(obj) && | 73 | else if (ttisstring(obj) && /* string convertible to number? */ |
| 73 | luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { | 74 | luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { |
| 74 | obj = &v; | 75 | obj = &v; |
| 75 | goto again; /* convert result from 'luaO_str2num' to a float */ | 76 | 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, | |||
| 178 | } | 179 | } |
| 179 | 180 | ||
| 180 | 181 | ||
| 182 | /* | ||
| 183 | ** Main function for table access (invoking metamethods if needed). | ||
| 184 | ** Compute 'val = t[key]' | ||
| 185 | */ | ||
| 181 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | 186 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { |
| 182 | int loop; | 187 | int loop; /* counter to avoid infinite loops */ |
| 183 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 188 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
| 184 | const TValue *tm; | 189 | const TValue *tm; |
| 185 | if (ttistable(t)) { /* `t' is a table? */ | 190 | if (ttistable(t)) { /* `t' is a table? */ |
| @@ -187,32 +192,36 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
| 187 | const TValue *res = luaH_get(h, key); /* do a primitive get */ | 192 | const TValue *res = luaH_get(h, key); /* do a primitive get */ |
| 188 | if (!ttisnil(res) || /* result is not nil? */ | 193 | if (!ttisnil(res) || /* result is not nil? */ |
| 189 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ | 194 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ |
| 190 | setobj2s(L, val, res); | 195 | setobj2s(L, val, res); /* result is the raw get */ |
| 191 | return; | 196 | return; |
| 192 | } | 197 | } |
| 193 | /* else will try the tag method */ | 198 | /* else will try metamethod */ |
| 194 | } | 199 | } |
| 195 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) | 200 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) |
| 196 | luaG_typeerror(L, t, "index"); | 201 | luaG_typeerror(L, t, "index"); /* no metamethod */ |
| 197 | if (ttisfunction(tm)) { | 202 | if (ttisfunction(tm)) { /* metamethod is a function */ |
| 198 | luaT_callTM(L, tm, t, key, val, 1); | 203 | luaT_callTM(L, tm, t, key, val, 1); |
| 199 | return; | 204 | return; |
| 200 | } | 205 | } |
| 201 | t = tm; /* else repeat with 'tm' */ | 206 | t = tm; /* else repeat access over 'tm' */ |
| 202 | } | 207 | } |
| 203 | luaG_runerror(L, "gettable chain too long; possible loop"); | 208 | luaG_runerror(L, "gettable chain too long; possible loop"); |
| 204 | } | 209 | } |
| 205 | 210 | ||
| 206 | 211 | ||
| 212 | /* | ||
| 213 | ** Main function for table assignment (invoking metamethods if needed). | ||
| 214 | ** Compute 't[key] = val' | ||
| 215 | */ | ||
| 207 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | 216 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { |
| 208 | int loop; | 217 | int loop; /* counter to avoid infinite loops */ |
| 209 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 218 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
| 210 | const TValue *tm; | 219 | const TValue *tm; |
| 211 | if (ttistable(t)) { /* `t' is a table? */ | 220 | if (ttistable(t)) { /* `t' is a table? */ |
| 212 | Table *h = hvalue(t); | 221 | Table *h = hvalue(t); |
| 213 | TValue *oldval = cast(TValue *, luaH_get(h, key)); | 222 | TValue *oldval = cast(TValue *, luaH_get(h, key)); |
| 214 | /* if previous value is not nil, there must be a previous entry | 223 | /* if previous value is not nil, there must be a previous entry |
| 215 | in the table; moreover, a metamethod has no relevance */ | 224 | in the table; a metamethod has no relevance */ |
| 216 | if (!ttisnil(oldval) || | 225 | if (!ttisnil(oldval) || |
| 217 | /* previous value is nil; must check the metamethod */ | 226 | /* previous value is nil; must check the metamethod */ |
| 218 | ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && | 227 | ((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) { | |||
| 232 | else /* not a table; check metamethod */ | 241 | else /* not a table; check metamethod */ |
| 233 | if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) | 242 | if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) |
| 234 | luaG_typeerror(L, t, "index"); | 243 | luaG_typeerror(L, t, "index"); |
| 235 | /* there is a metamethod */ | 244 | /* try the metamethod */ |
| 236 | if (ttisfunction(tm)) { | 245 | if (ttisfunction(tm)) { |
| 237 | luaT_callTM(L, tm, t, key, val, 0); | 246 | luaT_callTM(L, tm, t, key, val, 0); |
| 238 | return; | 247 | return; |
| 239 | } | 248 | } |
| 240 | t = tm; /* else repeat with 'tm' */ | 249 | t = tm; /* else repeat assginment over 'tm' */ |
| 241 | } | 250 | } |
| 242 | luaG_runerror(L, "settable chain too long; possible loop"); | 251 | luaG_runerror(L, "settable chain too long; possible loop"); |
| 243 | } | 252 | } |
| 244 | 253 | ||
| 245 | 254 | ||
| 255 | /* | ||
| 256 | ** Compare two strings 'ls' x 'rs', returning an integer smaller-equal- | ||
| 257 | ** -larger than zero if 'ls' is smaller-equal-larger than 'rs'. | ||
| 258 | ** The code is a little tricky because it allows '\0' in the strings | ||
| 259 | ** and it uses 'strcoll' (to respect locales) for each segments | ||
| 260 | ** of the strings. | ||
| 261 | */ | ||
| 246 | static int l_strcmp (const TString *ls, const TString *rs) { | 262 | static int l_strcmp (const TString *ls, const TString *rs) { |
| 247 | const char *l = getstr(ls); | 263 | const char *l = getstr(ls); |
| 248 | size_t ll = ls->tsv.len; | 264 | size_t ll = ls->tsv.len; |
| 249 | const char *r = getstr(rs); | 265 | const char *r = getstr(rs); |
| 250 | size_t lr = rs->tsv.len; | 266 | size_t lr = rs->tsv.len; |
| 251 | for (;;) { | 267 | for (;;) { /* for each segment */ |
| 252 | int temp = strcoll(l, r); | 268 | int temp = strcoll(l, r); |
| 253 | if (temp != 0) return temp; | 269 | if (temp != 0) /* not equal? */ |
| 254 | else { /* strings are equal up to a `\0' */ | 270 | return temp; /* done */ |
| 271 | else { /* strings are equal up to a '\0' */ | ||
| 255 | size_t len = strlen(l); /* index of first `\0' in both strings */ | 272 | size_t len = strlen(l); /* index of first `\0' in both strings */ |
| 256 | if (len == lr) /* r is finished? */ | 273 | if (len == lr) /* 'rs' is finished? */ |
| 257 | return (len == ll) ? 0 : 1; | 274 | return (len == ll) ? 0 : 1; /* check 'ls' */ |
| 258 | else if (len == ll) /* l is finished? */ | 275 | else if (len == ll) /* 'ls' is finished? */ |
| 259 | return -1; /* l is smaller than r (because r is not finished) */ | 276 | return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */ |
| 260 | /* both strings longer than `len'; go on comparing (after the `\0') */ | 277 | /* both strings longer than `len'; go on comparing after the '\0' */ |
| 261 | len++; | 278 | len++; |
| 262 | l += len; ll -= len; r += len; lr -= len; | 279 | l += len; ll -= len; r += len; lr -= len; |
| 263 | } | 280 | } |
| @@ -265,29 +282,35 @@ static int l_strcmp (const TString *ls, const TString *rs) { | |||
| 265 | } | 282 | } |
| 266 | 283 | ||
| 267 | 284 | ||
| 285 | /* | ||
| 286 | ** Main operation less than; return 'l < r'. | ||
| 287 | */ | ||
| 268 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { | 288 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { |
| 269 | int res; | 289 | int res; |
| 270 | lua_Number nl, nr; | 290 | lua_Number nl, nr; |
| 271 | if (ttisinteger(l) && ttisinteger(r)) | 291 | if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */ |
| 272 | return (ivalue(l) < ivalue(r)); | 292 | return (ivalue(l) < ivalue(r)); |
| 273 | else if (tofloat(l, &nl) && tofloat(r, &nr)) | 293 | else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */ |
| 274 | return luai_numlt(nl, nr); | 294 | return luai_numlt(nl, nr); |
| 275 | else if (ttisstring(l) && ttisstring(r)) | 295 | else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ |
| 276 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; | 296 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; |
| 277 | else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) | 297 | else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ |
| 278 | luaG_ordererror(L, l, r); | 298 | luaG_ordererror(L, l, r); /* error */ |
| 279 | return res; | 299 | return res; |
| 280 | } | 300 | } |
| 281 | 301 | ||
| 282 | 302 | ||
| 303 | /* | ||
| 304 | ** Main operation less than or equal to; return 'l <= r'. | ||
| 305 | */ | ||
| 283 | int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { | 306 | int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { |
| 284 | int res; | 307 | int res; |
| 285 | lua_Number nl, nr; | 308 | lua_Number nl, nr; |
| 286 | if (ttisinteger(l) && ttisinteger(r)) | 309 | if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */ |
| 287 | return (ivalue(l) <= ivalue(r)); | 310 | return (ivalue(l) <= ivalue(r)); |
| 288 | else if (tofloat(l, &nl) && tofloat(r, &nr)) | 311 | else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */ |
| 289 | return luai_numle(nl, nr); | 312 | return luai_numle(nl, nr); |
| 290 | else if (ttisstring(l) && ttisstring(r)) | 313 | else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ |
| 291 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; | 314 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; |
| 292 | else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ | 315 | else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ |
| 293 | return res; | 316 | return res; |
| @@ -298,15 +321,16 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { | |||
| 298 | 321 | ||
| 299 | 322 | ||
| 300 | /* | 323 | /* |
| 301 | ** equality of Lua values. L == NULL means raw equality (no metamethods) | 324 | ** Main operation for equality of Lua values; return 't1 == t2'. |
| 325 | ** L == NULL means raw equality (no metamethods) | ||
| 302 | */ | 326 | */ |
| 303 | int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { | 327 | int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { |
| 304 | const TValue *tm; | 328 | const TValue *tm; |
| 305 | if (ttype(t1) != ttype(t2)) { | 329 | if (ttype(t1) != ttype(t2)) { /* not the same variant? */ |
| 306 | if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) | 330 | if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) |
| 307 | return 0; /* only numbers can be equal with different variants */ | 331 | return 0; /* only numbers can be equal with different variants */ |
| 308 | else { /* two numbers with different variants */ | 332 | else { /* two numbers with different variants */ |
| 309 | lua_Number n1, n2; | 333 | lua_Number n1, n2; /* compare them as floats */ |
| 310 | lua_assert(ttisnumber(t1) && ttisnumber(t2)); | 334 | lua_assert(ttisnumber(t1) && ttisnumber(t2)); |
| 311 | cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2)); | 335 | cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2)); |
| 312 | return luai_numeq(n1, n2); | 336 | return luai_numeq(n1, n2); |
| @@ -343,8 +367,13 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { | |||
| 343 | } | 367 | } |
| 344 | 368 | ||
| 345 | 369 | ||
| 370 | /* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ | ||
| 346 | #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) | 371 | #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) |
| 347 | 372 | ||
| 373 | /* | ||
| 374 | ** Main operation for concatenation: concat 'total' values in the stack, | ||
| 375 | ** from 'L->top - total' up to 'L->top - 1'. | ||
| 376 | */ | ||
| 348 | void luaV_concat (lua_State *L, int total) { | 377 | void luaV_concat (lua_State *L, int total) { |
| 349 | lua_assert(total >= 2); | 378 | lua_assert(total >= 2); |
| 350 | do { | 379 | do { |
| @@ -372,12 +401,12 @@ void luaV_concat (lua_State *L, int total) { | |||
| 372 | buffer = luaZ_openspace(L, &G(L)->buff, tl); | 401 | buffer = luaZ_openspace(L, &G(L)->buff, tl); |
| 373 | tl = 0; | 402 | tl = 0; |
| 374 | n = i; | 403 | n = i; |
| 375 | do { /* concat all strings */ | 404 | do { /* copy all strings to buffer */ |
| 376 | size_t l = tsvalue(top-i)->len; | 405 | size_t l = tsvalue(top-i)->len; |
| 377 | memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); | 406 | memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); |
| 378 | tl += l; | 407 | tl += l; |
| 379 | } while (--i > 0); | 408 | } while (--i > 0); |
| 380 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); | 409 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); /* create result */ |
| 381 | } | 410 | } |
| 382 | total -= n-1; /* got 'n' strings to create 1 new */ | 411 | total -= n-1; /* got 'n' strings to create 1 new */ |
| 383 | L->top -= n-1; /* popped 'n' strings and pushed one */ | 412 | L->top -= n-1; /* popped 'n' strings and pushed one */ |
| @@ -385,6 +414,9 @@ void luaV_concat (lua_State *L, int total) { | |||
| 385 | } | 414 | } |
| 386 | 415 | ||
| 387 | 416 | ||
| 417 | /* | ||
| 418 | ** Main operation 'ra' = #rb'. | ||
| 419 | */ | ||
| 388 | void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { | 420 | void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { |
| 389 | const TValue *tm; | 421 | const TValue *tm; |
| 390 | switch (ttnov(rb)) { | 422 | switch (ttnov(rb)) { |
| @@ -410,15 +442,18 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { | |||
| 410 | } | 442 | } |
| 411 | 443 | ||
| 412 | 444 | ||
| 413 | lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { | 445 | /* |
| 414 | if (l_castS2U(y) + 1u <= 1u) { /* special cases: -1 or 0 */ | 446 | ** Integer division; return 'm // n'. |
| 415 | if (y == 0) | 447 | */ |
| 448 | lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { | ||
| 449 | if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ | ||
| 450 | if (n == 0) | ||
| 416 | luaG_runerror(L, "attempt to divide by zero"); | 451 | luaG_runerror(L, "attempt to divide by zero"); |
| 417 | return intop(-, 0, x); /* y==-1; avoid overflow with 0x80000...//-1 */ | 452 | return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ |
| 418 | } | 453 | } |
| 419 | else { | 454 | else { |
| 420 | lua_Integer d = x / y; /* perform division */ | 455 | lua_Integer d = m / n; /* perform division */ |
| 421 | if ((x ^ y) >= 0 || x % y == 0) /* same signal or no rest? */ | 456 | if ((m ^ n) >= 0 || m % n == 0) /* same signal or no rest? */ |
| 422 | return d; | 457 | return d; |
| 423 | else | 458 | else |
| 424 | return d - 1; /* correct 'div' for negative case */ | 459 | 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) { | |||
| 426 | } | 461 | } |
| 427 | 462 | ||
| 428 | 463 | ||
| 429 | lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { | 464 | /* |
| 430 | if (l_castS2U(y) + 1u <= 1u) { /* special cases: -1 or 0 */ | 465 | ** Integer modulus; return 'm % n'. |
| 431 | if (y == 0) | 466 | */ |
| 467 | lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { | ||
| 468 | if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ | ||
| 469 | if (n == 0) | ||
| 432 | luaG_runerror(L, "attempt to perform 'n%%0'"); | 470 | luaG_runerror(L, "attempt to perform 'n%%0'"); |
| 433 | return 0; /* y==-1; avoid overflow with 0x80000...%-1 */ | 471 | return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ |
| 434 | } | 472 | } |
| 435 | else { | 473 | else { |
| 436 | lua_Integer r = x % y; | 474 | lua_Integer r = m % n; |
| 437 | if (r == 0 || (x ^ y) >= 0) | 475 | if (r == 0 || (m ^ n) >= 0) |
| 438 | return r; | 476 | return r; |
| 439 | else | 477 | else |
| 440 | return r + y; /* correct 'mod' for negative case */ | 478 | return r + n; /* correct 'mod' for negative case */ |
| 441 | } | 479 | } |
| 442 | } | 480 | } |
| 443 | 481 | ||
| 444 | 482 | ||
| 445 | lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { | 483 | lua_Integer luaV_pow (lua_Integer m, lua_Integer n) { |
| 446 | lua_assert(y >= 0); | 484 | lua_assert(n >= 0); |
| 447 | if (y == 0) | 485 | if (n == 0) |
| 448 | return 1; /* x^0 == 1 */ | 486 | return 1; /* m^0 == 1 */ |
| 449 | else { | 487 | else { |
| 450 | lua_Integer r = 1; | 488 | lua_Integer r = 1; |
| 451 | for (; y > 1; y >>= 1) { | 489 | for (; n > 1; n >>= 1) { |
| 452 | if (y & 1) r = intop(*, r, x); | 490 | if (n & 1) r = intop(*, r, m); |
| 453 | x = intop(*, x, x); | 491 | m = intop(*, m, m); |
| 454 | } | 492 | } |
| 455 | r = intop(*, r, x); | 493 | r = intop(*, r, m); |
| 456 | return r; | 494 | return r; |
| 457 | } | 495 | } |
| 458 | } | 496 | } |
