commit d742a193e57029d973aff0a5eb04d8ddd03fa0ff
parent e4a38eb0e828e9589c391171e2e1904a3b9698e7
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Thu, 22 Oct 2020 15:54:19 -0300
Comments
Diffstat:
3 files changed, 34 insertions(+), 26 deletions(-)
diff --git a/llex.c b/llex.c
@@ -254,9 +254,10 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
/*
-** reads a sequence '[=*[' or ']=*]', leaving the last bracket.
-** If sequence is well formed, return its number of '='s + 2; otherwise,
-** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...').
+** read a sequence '[=*[' or ']=*]', leaving the last bracket. If
+** sequence is well formed, return its number of '='s + 2; otherwise,
+** return 1 if it is a single bracket (no '='s and no 2nd bracket);
+** otherwise (an unfinished '[==...') return 0.
*/
static size_t skip_sep (LexState *ls) {
size_t count = 0;
@@ -481,34 +482,34 @@ static int llex (LexState *ls, SemInfo *seminfo) {
}
case '=': {
next(ls);
- if (check_next1(ls, '=')) return TK_EQ;
+ if (check_next1(ls, '=')) return TK_EQ; /* '==' */
else return '=';
}
case '<': {
next(ls);
- if (check_next1(ls, '=')) return TK_LE;
- else if (check_next1(ls, '<')) return TK_SHL;
+ if (check_next1(ls, '=')) return TK_LE; /* '<=' */
+ else if (check_next1(ls, '<')) return TK_SHL; /* '<<' */
else return '<';
}
case '>': {
next(ls);
- if (check_next1(ls, '=')) return TK_GE;
- else if (check_next1(ls, '>')) return TK_SHR;
+ if (check_next1(ls, '=')) return TK_GE; /* '>=' */
+ else if (check_next1(ls, '>')) return TK_SHR; /* '>>' */
else return '>';
}
case '/': {
next(ls);
- if (check_next1(ls, '/')) return TK_IDIV;
+ if (check_next1(ls, '/')) return TK_IDIV; /* '//' */
else return '/';
}
case '~': {
next(ls);
- if (check_next1(ls, '=')) return TK_NE;
+ if (check_next1(ls, '=')) return TK_NE; /* '~=' */
else return '~';
}
case ':': {
next(ls);
- if (check_next1(ls, ':')) return TK_DBCOLON;
+ if (check_next1(ls, ':')) return TK_DBCOLON; /* '::' */
else return ':';
}
case '"': case '\'': { /* short literal strings */
@@ -547,7 +548,7 @@ static int llex (LexState *ls, SemInfo *seminfo) {
return TK_NAME;
}
}
- else { /* single-char tokens (+ - / ...) */
+ else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */
int c = ls->current;
next(ls);
return c;
diff --git a/lparser.c b/lparser.c
@@ -945,7 +945,7 @@ static void setvararg (FuncState *fs, int nparams) {
static void parlist (LexState *ls) {
- /* parlist -> [ param { ',' param } ] */
+ /* parlist -> [ {NAME ','} (NAME | '...') ] */
FuncState *fs = ls->fs;
Proto *f = fs->f;
int nparams = 0;
@@ -953,12 +953,12 @@ static void parlist (LexState *ls) {
if (ls->t.token != ')') { /* is 'parlist' not empty? */
do {
switch (ls->t.token) {
- case TK_NAME: { /* param -> NAME */
+ case TK_NAME: {
new_localvar(ls, str_checkname(ls));
nparams++;
break;
}
- case TK_DOTS: { /* param -> '...' */
+ case TK_DOTS: {
luaX_next(ls);
isvararg = 1;
break;
@@ -1752,7 +1752,7 @@ static void checktoclose (LexState *ls, int level) {
static void localstat (LexState *ls) {
- /* stat -> LOCAL ATTRIB NAME {',' ATTRIB NAME} ['=' explist] */
+ /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */
FuncState *fs = ls->fs;
int toclose = -1; /* index of to-be-closed variable (if any) */
Vardesc *var; /* last variable */
diff --git a/ltable.c b/ltable.c
@@ -166,17 +166,24 @@ static Node *mainpositionTV (const Table *t, const TValue *key) {
/*
-** Check whether key 'k1' is equal to the key in node 'n2'.
-** This equality is raw, so there are no metamethods. Floats
-** with integer values have been normalized, so integers cannot
-** be equal to floats. It is assumed that 'eqshrstr' is simply
-** pointer equality, so that short strings are handled in the
-** default case.
+** Check whether key 'k1' is equal to the key in node 'n2'. This
+** equality is raw, so there are no metamethods. Floats with integer
+** values have been normalized, so integers cannot be equal to
+** floats. It is assumed that 'eqshrstr' is simply pointer equality, so
+** that short strings are handled in the default case.
** A true 'deadok' means to accept dead keys as equal to their original
-** values, which can only happen if the original key was collectable.
-** All dead values are compared in the default case, by pointer
-** identity. (Note that dead long strings are also compared by
-** identity).
+** values. All dead keys are compared in the default case, by pointer
+** identity. (Only collectable objects can produce dead keys.) Note that
+** dead long strings are also compared by identity.
+** Once a key is dead, its corresponding value may be collected, and
+** then another value can be created with the same address. If this
+** other value is given to 'next', 'equalkey' will signal a false
+** positive. In a regular traversal, this situation should never happen,
+** as all keys given to 'next' came from the table itself, and therefore
+** could not have been collected. Outside a regular traversal, we
+** have garbage in, garbage out. What is relevant is that this false
+** positive does not break anything. (In particular, 'next' will return
+** some other valid item on the table or nil.)
*/
static int equalkey (const TValue *k1, const Node *n2, int deadok) {
if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */