diff options
-rw-r--r-- | lbaselib.c | 20 | ||||
-rw-r--r-- | lcode.c | 63 | ||||
-rw-r--r-- | lcode.h | 4 | ||||
-rw-r--r-- | ljumptab.h | 2 | ||||
-rw-r--r-- | llex.c | 4 | ||||
-rw-r--r-- | llex.h | 4 | ||||
-rw-r--r-- | lopcodes.c | 6 | ||||
-rw-r--r-- | lopcodes.h | 5 | ||||
-rw-r--r-- | lparser.c | 29 | ||||
-rw-r--r-- | lparser.h | 5 | ||||
-rw-r--r-- | lvm.c | 14 |
11 files changed, 113 insertions, 43 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.321 2018/02/27 17:48:28 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.322 2018/02/27 18:47:32 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -170,22 +170,6 @@ static int luaB_rawset (lua_State *L) { | |||
170 | } | 170 | } |
171 | 171 | ||
172 | 172 | ||
173 | static int luaB_keyin (lua_State *L) { | ||
174 | luaL_checkany(L, 2); /* ensures a first argument too */ | ||
175 | lua_settop(L, 2); | ||
176 | lua_pushboolean(L, lua_keyin(L, 1)); | ||
177 | return 1; | ||
178 | } | ||
179 | |||
180 | |||
181 | static int luaB_removekey (lua_State *L) { | ||
182 | luaL_checkany(L, 2); /* ensures a first argument too */ | ||
183 | lua_settop(L, 2); | ||
184 | lua_removekey(L, 1); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | |||
189 | static int pushmode (lua_State *L, int oldmode) { | 173 | static int pushmode (lua_State *L, int oldmode) { |
190 | lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" : "generational"); | 174 | lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" : "generational"); |
191 | return 1; | 175 | return 1; |
@@ -503,8 +487,6 @@ static const luaL_Reg base_funcs[] = { | |||
503 | {"rawlen", luaB_rawlen}, | 487 | {"rawlen", luaB_rawlen}, |
504 | {"rawget", luaB_rawget}, | 488 | {"rawget", luaB_rawget}, |
505 | {"rawset", luaB_rawset}, | 489 | {"rawset", luaB_rawset}, |
506 | {"keyin", luaB_keyin}, | ||
507 | {"removekey", luaB_removekey}, | ||
508 | {"select", luaB_select}, | 490 | {"select", luaB_select}, |
509 | {"setmetatable", luaB_setmetatable}, | 491 | {"setmetatable", luaB_setmetatable}, |
510 | {"tonumber", luaB_tonumber}, | 492 | {"tonumber", luaB_tonumber}, |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.157 2018/02/21 15:49:32 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.158 2018/02/26 14:16:05 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -40,6 +40,14 @@ | |||
40 | static int codesJ (FuncState *fs, OpCode o, int sj, int k); | 40 | static int codesJ (FuncState *fs, OpCode o, int sj, int k); |
41 | 41 | ||
42 | 42 | ||
43 | |||
44 | /* semantic error */ | ||
45 | l_noret luaK_semerror (LexState *ls, const char *msg) { | ||
46 | ls->t.token = 0; /* remove "near <token>" from final message */ | ||
47 | luaX_syntaxerror(ls, msg); | ||
48 | } | ||
49 | |||
50 | |||
43 | /* | 51 | /* |
44 | ** If expression is a numeric constant, fills 'v' with its value | 52 | ** If expression is a numeric constant, fills 'v' with its value |
45 | ** and returns 1. Otherwise, returns 0. | 53 | ** and returns 1. Otherwise, returns 0. |
@@ -670,6 +678,10 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
670 | e->k = VNONRELOC; /* becomes a non-relocatable value */ | 678 | e->k = VNONRELOC; /* becomes a non-relocatable value */ |
671 | break; | 679 | break; |
672 | } | 680 | } |
681 | case VUNDEF: { /* not a real expression */ | ||
682 | luaK_semerror(fs->ls, "'undef' is not a value!!"); | ||
683 | break; | ||
684 | } | ||
673 | case VUPVAL: { /* move value to some (pending) register */ | 685 | case VUPVAL: { /* move value to some (pending) register */ |
674 | e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); | 686 | e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); |
675 | e->k = VRELOC; | 687 | e->k = VRELOC; |
@@ -1398,6 +1410,48 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | |||
1398 | } | 1410 | } |
1399 | 1411 | ||
1400 | 1412 | ||
1413 | static void normalizeindexed (FuncState *fs, expdesc *v) { | ||
1414 | if (v->k != VINDEXED) { /* not in proper form? */ | ||
1415 | int key = fs->freereg; /* register with key value */ | ||
1416 | luaK_reserveregs(fs, 1); | ||
1417 | switch (v->k) { | ||
1418 | case VINDEXI: | ||
1419 | luaK_int(fs, key, v->u.ind.idx); | ||
1420 | break; | ||
1421 | case VINDEXSTR: | ||
1422 | luaK_codek(fs, key, v->u.ind.idx); | ||
1423 | break; | ||
1424 | case VINDEXUP: | ||
1425 | luaK_codek(fs, key, v->u.ind.idx); | ||
1426 | luaK_codeABC(fs, OP_GETUPVAL, fs->freereg, v->u.ind.t, 0); | ||
1427 | v->u.ind.t = fs->freereg; | ||
1428 | luaK_reserveregs(fs, 1); /* one more register for the upvalue */ | ||
1429 | break; | ||
1430 | default: | ||
1431 | luaK_semerror(fs->ls, "'undef' is not a value!!"); | ||
1432 | break; | ||
1433 | } | ||
1434 | v->u.ind.idx = key; | ||
1435 | v->k = VINDEXED; | ||
1436 | } | ||
1437 | freeregs(fs, v->u.ind.t, v->u.ind.idx); | ||
1438 | } | ||
1439 | |||
1440 | |||
1441 | static void codeisdef (FuncState *fs, int eq, expdesc *v) { | ||
1442 | normalizeindexed(fs, v); | ||
1443 | v->u.info = luaK_codeABCk(fs, OP_ISDEF, 0, v->u.ind.t, v->u.ind.idx, eq); | ||
1444 | v->k = VRELOC; | ||
1445 | } | ||
1446 | |||
1447 | |||
1448 | void luaK_codeundef (FuncState *fs, expdesc *v) { | ||
1449 | normalizeindexed(fs, v); | ||
1450 | v->u.info = luaK_codeABC(fs, OP_UNDEF, v->u.ind.t, v->u.ind.idx, 0); | ||
1451 | v->k = VRELOC; | ||
1452 | } | ||
1453 | |||
1454 | |||
1401 | /* | 1455 | /* |
1402 | ** Apply prefix operation 'op' to expression 'e'. | 1456 | ** Apply prefix operation 'op' to expression 'e'. |
1403 | */ | 1457 | */ |
@@ -1446,7 +1500,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
1446 | break; | 1500 | break; |
1447 | } | 1501 | } |
1448 | case OPR_EQ: case OPR_NE: { | 1502 | case OPR_EQ: case OPR_NE: { |
1449 | if (!tonumeral(v, NULL)) | 1503 | if (!tonumeral(v, NULL) && fs->ls->t.token != TK_UNDEF) |
1450 | luaK_exp2RK(fs, v); | 1504 | luaK_exp2RK(fs, v); |
1451 | /* else keep numeral, which may be an immediate operand */ | 1505 | /* else keep numeral, which may be an immediate operand */ |
1452 | break; | 1506 | break; |
@@ -1543,7 +1597,10 @@ void luaK_posfix (FuncState *fs, BinOpr opr, | |||
1543 | break; | 1597 | break; |
1544 | } | 1598 | } |
1545 | case OPR_EQ: case OPR_NE: { | 1599 | case OPR_EQ: case OPR_NE: { |
1546 | codeeq(fs, opr, e1, e2); | 1600 | if (e2->k == VUNDEF) |
1601 | codeisdef(fs, opr == OPR_NE, e1); | ||
1602 | else | ||
1603 | codeeq(fs, opr, e1, e2); | ||
1547 | break; | 1604 | break; |
1548 | } | 1605 | } |
1549 | case OPR_LT: case OPR_LE: { | 1606 | case OPR_LT: case OPR_LE: { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.69 2017/11/30 13:29:18 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.70 2017/12/18 15:44:44 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -89,6 +89,8 @@ LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, | |||
89 | expdesc *v2, int line); | 89 | expdesc *v2, int line); |
90 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); | 90 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); |
91 | LUAI_FUNC void luaK_finish (FuncState *fs); | 91 | LUAI_FUNC void luaK_finish (FuncState *fs); |
92 | LUAI_FUNC void luaK_codeundef (FuncState *fs, expdesc *e); | ||
93 | LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); | ||
92 | 94 | ||
93 | 95 | ||
94 | #endif | 96 | #endif |
@@ -78,6 +78,8 @@ static void *disptab[] = { | |||
78 | &&L_OP_GEI, | 78 | &&L_OP_GEI, |
79 | &&L_OP_TEST, | 79 | &&L_OP_TEST, |
80 | &&L_OP_TESTSET, | 80 | &&L_OP_TESTSET, |
81 | &&L_OP_UNDEF, | ||
82 | &&L_OP_ISDEF, | ||
81 | &&L_OP_CALL, | 83 | &&L_OP_CALL, |
82 | &&L_OP_TAILCALL, | 84 | &&L_OP_TAILCALL, |
83 | &&L_OP_RETURN, | 85 | &&L_OP_RETURN, |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.c,v 2.99 2018/01/28 15:13:26 roberto Exp roberto $ | 2 | ** $Id: llex.c,v 2.100 2018/02/23 13:13:31 roberto Exp roberto $ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -41,7 +41,7 @@ static const char *const luaX_tokens [] = { | |||
41 | "and", "break", "do", "else", "elseif", | 41 | "and", "break", "do", "else", "elseif", |
42 | "end", "false", "for", "function", "goto", "if", | 42 | "end", "false", "for", "function", "goto", "if", |
43 | "in", "local", "nil", "not", "or", "repeat", | 43 | "in", "local", "nil", "not", "or", "repeat", |
44 | "return", "then", "true", "until", "while", | 44 | "return", "then", "true", "undef", "until", "while", |
45 | "//", "..", "...", "==", ">=", "<=", "~=", | 45 | "//", "..", "...", "==", ">=", "<=", "~=", |
46 | "<<", ">>", "::", "<eof>", | 46 | "<<", ">>", "::", "<eof>", |
47 | "<number>", "<integer>", "<name>", "<string>" | 47 | "<number>", "<integer>", "<name>", "<string>" |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.h,v 1.79 2016/05/02 14:02:12 roberto Exp roberto $ | 2 | ** $Id: llex.h,v 1.80 2018/01/28 15:13:26 roberto Exp roberto $ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -28,7 +28,7 @@ enum RESERVED { | |||
28 | TK_AND = FIRST_RESERVED, TK_BREAK, | 28 | TK_AND = FIRST_RESERVED, TK_BREAK, |
29 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, | 29 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, |
30 | TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, | 30 | TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, |
31 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, | 31 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNDEF, TK_UNTIL, TK_WHILE, |
32 | /* other terminal symbols */ | 32 | /* other terminal symbols */ |
33 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, | 33 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, |
34 | TK_SHL, TK_SHR, | 34 | TK_SHL, TK_SHR, |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.78 2018/02/15 15:34:29 roberto Exp roberto $ | 2 | ** $Id: lopcodes.c,v 1.79 2018/02/21 15:49:32 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -79,6 +79,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
79 | "GEI", | 79 | "GEI", |
80 | "TEST", | 80 | "TEST", |
81 | "TESTSET", | 81 | "TESTSET", |
82 | "UNDEF", | ||
83 | "ISDEF", | ||
82 | "CALL", | 84 | "CALL", |
83 | "TAILCALL", | 85 | "TAILCALL", |
84 | "RETURN", | 86 | "RETURN", |
@@ -162,6 +164,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
162 | ,opmode(0, 0, 1, 0, iABC) /* OP_GEI */ | 164 | ,opmode(0, 0, 1, 0, iABC) /* OP_GEI */ |
163 | ,opmode(0, 0, 1, 0, iABC) /* OP_TEST */ | 165 | ,opmode(0, 0, 1, 0, iABC) /* OP_TEST */ |
164 | ,opmode(0, 0, 1, 1, iABC) /* OP_TESTSET */ | 166 | ,opmode(0, 0, 1, 1, iABC) /* OP_TESTSET */ |
167 | ,opmode(0, 0, 0, 0, iABC) /* OP_UNDEF */ | ||
168 | ,opmode(0, 0, 0, 1, iABC) /* OP_ISDEF */ | ||
165 | ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ | 169 | ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ |
166 | ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */ | 170 | ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */ |
167 | ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */ | 171 | ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.188 2018/02/15 15:34:29 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.189 2018/02/21 15:49:32 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -266,6 +266,9 @@ OP_GEI,/* A sB if ((R(A) >= sB) ~= k) then pc++ */ | |||
266 | OP_TEST,/* A if (not R(A) == k) then pc++ */ | 266 | OP_TEST,/* A if (not R(A) == k) then pc++ */ |
267 | OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */ | 267 | OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */ |
268 | 268 | ||
269 | OP_UNDEF,/* A B R(A)[R(B)] = undef */ | ||
270 | OP_ISDEF,/* A B C R(A) = (R(B)[R(C)] == undef */ | ||
271 | |||
269 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ | 272 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ |
270 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ | 273 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ |
271 | 274 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.177 2018/02/09 15:16:06 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.178 2018/02/17 19:20:00 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -65,13 +65,6 @@ static void statement (LexState *ls); | |||
65 | static void expr (LexState *ls, expdesc *v); | 65 | static void expr (LexState *ls, expdesc *v); |
66 | 66 | ||
67 | 67 | ||
68 | /* semantic error */ | ||
69 | static l_noret semerror (LexState *ls, const char *msg) { | ||
70 | ls->t.token = 0; /* remove "near <token>" from final message */ | ||
71 | luaX_syntaxerror(ls, msg); | ||
72 | } | ||
73 | |||
74 | |||
75 | static l_noret error_expected (LexState *ls, int token) { | 68 | static l_noret error_expected (LexState *ls, int token) { |
76 | luaX_syntaxerror(ls, | 69 | luaX_syntaxerror(ls, |
77 | luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); | 70 | luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); |
@@ -347,7 +340,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) { | |||
347 | const char *msg = luaO_pushfstring(ls->L, | 340 | const char *msg = luaO_pushfstring(ls->L, |
348 | "<goto %s> at line %d jumps into the scope of local '%s'", | 341 | "<goto %s> at line %d jumps into the scope of local '%s'", |
349 | getstr(gt->name), gt->line, getstr(vname)); | 342 | getstr(gt->name), gt->line, getstr(vname)); |
350 | semerror(ls, msg); | 343 | luaK_semerror(ls, msg); |
351 | } | 344 | } |
352 | luaK_patchgoto(fs, gt->pc, label->pc, 1); | 345 | luaK_patchgoto(fs, gt->pc, label->pc, 1); |
353 | /* remove goto from pending list */ | 346 | /* remove goto from pending list */ |
@@ -477,7 +470,7 @@ static void fixbreaks (FuncState *fs, BlockCnt *bl) { | |||
477 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { | 470 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { |
478 | const char *msg = "no visible label '%s' for <goto> at line %d"; | 471 | const char *msg = "no visible label '%s' for <goto> at line %d"; |
479 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); | 472 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); |
480 | semerror(ls, msg); | 473 | luaK_semerror(ls, msg); |
481 | } | 474 | } |
482 | 475 | ||
483 | 476 | ||
@@ -900,6 +893,11 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
900 | singlevar(ls, v); | 893 | singlevar(ls, v); |
901 | return; | 894 | return; |
902 | } | 895 | } |
896 | case TK_UNDEF: { | ||
897 | luaX_next(ls); | ||
898 | init_exp(v, VUNDEF, 0); | ||
899 | return; | ||
900 | } | ||
903 | default: { | 901 | default: { |
904 | luaX_syntaxerror(ls, "unexpected symbol"); | 902 | luaX_syntaxerror(ls, "unexpected symbol"); |
905 | } | 903 | } |
@@ -1185,6 +1183,10 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | |||
1185 | else { /* assignment -> '=' explist */ | 1183 | else { /* assignment -> '=' explist */ |
1186 | int nexps; | 1184 | int nexps; |
1187 | checknext(ls, '='); | 1185 | checknext(ls, '='); |
1186 | if (nvars == 1 && testnext(ls, TK_UNDEF)) { | ||
1187 | luaK_codeundef(ls->fs, &lh->v); | ||
1188 | return; | ||
1189 | } | ||
1188 | nexps = explist(ls, &e); | 1190 | nexps = explist(ls, &e); |
1189 | if (nexps != nvars) | 1191 | if (nexps != nvars) |
1190 | adjust_assign(ls, nvars, nexps, &e); | 1192 | adjust_assign(ls, nvars, nexps, &e); |
@@ -1237,7 +1239,7 @@ static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { | |||
1237 | const char *msg = luaO_pushfstring(fs->ls->L, | 1239 | const char *msg = luaO_pushfstring(fs->ls->L, |
1238 | "label '%s' already defined on line %d", | 1240 | "label '%s' already defined on line %d", |
1239 | getstr(label), ll->arr[i].line); | 1241 | getstr(label), ll->arr[i].line); |
1240 | semerror(fs->ls, msg); | 1242 | luaK_semerror(fs->ls, msg); |
1241 | } | 1243 | } |
1242 | } | 1244 | } |
1243 | } | 1245 | } |
@@ -1650,6 +1652,11 @@ static void statement (LexState *ls) { | |||
1650 | luaX_next(ls); /* skip LOCAL */ | 1652 | luaX_next(ls); /* skip LOCAL */ |
1651 | if (testnext(ls, TK_FUNCTION)) /* local function? */ | 1653 | if (testnext(ls, TK_FUNCTION)) /* local function? */ |
1652 | localfunc(ls); | 1654 | localfunc(ls); |
1655 | else if (testnext(ls, TK_UNDEF)) | ||
1656 | (void)0; /* ignore */ | ||
1657 | /* old versions may need to declare 'local undef' | ||
1658 | when using 'undef' with no environment; so this | ||
1659 | version accepts (and ignores) these declarations */ | ||
1653 | else | 1660 | else |
1654 | localstat(ls); | 1661 | localstat(ls); |
1655 | break; | 1662 | break; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.h,v 1.79 2017/11/30 13:29:18 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.80 2017/12/14 14:24:02 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -52,7 +52,8 @@ typedef enum { | |||
52 | VRELOC, /* expression can put result in any register; | 52 | VRELOC, /* expression can put result in any register; |
53 | info = instruction pc */ | 53 | info = instruction pc */ |
54 | VCALL, /* expression is a function call; info = instruction pc */ | 54 | VCALL, /* expression is a function call; info = instruction pc */ |
55 | VVARARG /* vararg expression; info = instruction pc */ | 55 | VVARARG, /* vararg expression; info = instruction pc */ |
56 | VUNDEF /* the 'undef' "expression" */ | ||
56 | } expkind; | 57 | } expkind; |
57 | 58 | ||
58 | 59 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.348 2018/02/26 14:16:05 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.349 2018/03/02 18:59:19 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 | */ |
@@ -1552,6 +1552,18 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1552 | } | 1552 | } |
1553 | vmbreak; | 1553 | vmbreak; |
1554 | } | 1554 | } |
1555 | vmcase(OP_UNDEF) { | ||
1556 | TValue *rb = vRB(i); | ||
1557 | luaT_keydef(L, vra, rb, 1); | ||
1558 | vmbreak; | ||
1559 | } | ||
1560 | vmcase(OP_ISDEF) { | ||
1561 | TValue *rb = vRB(i); | ||
1562 | TValue *rc = vRC(i); | ||
1563 | int res = luaT_keydef(L, rb, rc, 0); | ||
1564 | setbvalue(vra, res == GETARG_k(i)); | ||
1565 | vmbreak; | ||
1566 | } | ||
1555 | vmcase(OP_CALL) { | 1567 | vmcase(OP_CALL) { |
1556 | int b = GETARG_B(i); | 1568 | int b = GETARG_B(i); |
1557 | int nresults = GETARG_C(i) - 1; | 1569 | int nresults = GETARG_C(i) - 1; |