Skip to content

Commit 4a1612f

Browse files
committed
new experimental syntax using reserved word 'undef'
1 parent 464658b commit 4a1612f

11 files changed

Lines changed: 113 additions & 43 deletions

File tree

lbaselib.c

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Basic library
44
** See Copyright Notice in lua.h
55
*/
@@ -170,22 +170,6 @@ static int luaB_rawset (lua_State *L) {
170170
}
171171

172172

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-
189173
static int pushmode (lua_State *L, int oldmode) {
190174
lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" : "generational");
191175
return 1;
@@ -503,8 +487,6 @@ static const luaL_Reg base_funcs[] = {
503487
{"rawlen", luaB_rawlen},
504488
{"rawget", luaB_rawget},
505489
{"rawset", luaB_rawset},
506-
{"keyin", luaB_keyin},
507-
{"removekey", luaB_removekey},
508490
{"select", luaB_select},
509491
{"setmetatable", luaB_setmetatable},
510492
{"tonumber", luaB_tonumber},

lcode.c

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Code generator for Lua
44
** See Copyright Notice in lua.h
55
*/
@@ -40,6 +40,14 @@
4040
static int codesJ (FuncState *fs, OpCode o, int sj, int k);
4141

4242

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+
4351
/*
4452
** If expression is a numeric constant, fills 'v' with its value
4553
** and returns 1. Otherwise, returns 0.
@@ -670,6 +678,10 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
670678
e->k = VNONRELOC; /* becomes a non-relocatable value */
671679
break;
672680
}
681+
case VUNDEF: { /* not a real expression */
682+
luaK_semerror(fs->ls, "'undef' is not a value!!");
683+
break;
684+
}
673685
case VUPVAL: { /* move value to some (pending) register */
674686
e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
675687
e->k = VRELOC;
@@ -1398,6 +1410,48 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
13981410
}
13991411

14001412

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+
14011455
/*
14021456
** Apply prefix operation 'op' to expression 'e'.
14031457
*/
@@ -1446,7 +1500,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
14461500
break;
14471501
}
14481502
case OPR_EQ: case OPR_NE: {
1449-
if (!tonumeral(v, NULL))
1503+
if (!tonumeral(v, NULL) && fs->ls->t.token != TK_UNDEF)
14501504
luaK_exp2RK(fs, v);
14511505
/* else keep numeral, which may be an immediate operand */
14521506
break;
@@ -1543,7 +1597,10 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
15431597
break;
15441598
}
15451599
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);
15471604
break;
15481605
}
15491606
case OPR_LT: case OPR_LE: {

lcode.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Code generator for Lua
44
** See Copyright Notice in lua.h
55
*/
@@ -89,6 +89,8 @@ LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
8989
expdesc *v2, int line);
9090
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
9191
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);
9294

9395

9496
#endif

ljumptab.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ static void *disptab[] = {
7878
&&L_OP_GEI,
7979
&&L_OP_TEST,
8080
&&L_OP_TESTSET,
81+
&&L_OP_UNDEF,
82+
&&L_OP_ISDEF,
8183
&&L_OP_CALL,
8284
&&L_OP_TAILCALL,
8385
&&L_OP_RETURN,

llex.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Lexical Analyzer
44
** See Copyright Notice in lua.h
55
*/
@@ -41,7 +41,7 @@ static const char *const luaX_tokens [] = {
4141
"and", "break", "do", "else", "elseif",
4242
"end", "false", "for", "function", "goto", "if",
4343
"in", "local", "nil", "not", "or", "repeat",
44-
"return", "then", "true", "until", "while",
44+
"return", "then", "true", "undef", "until", "while",
4545
"//", "..", "...", "==", ">=", "<=", "~=",
4646
"<<", ">>", "::", "<eof>",
4747
"<number>", "<integer>", "<name>", "<string>"

llex.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Lexical Analyzer
44
** See Copyright Notice in lua.h
55
*/
@@ -28,7 +28,7 @@ enum RESERVED {
2828
TK_AND = FIRST_RESERVED, TK_BREAK,
2929
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
3030
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,
3232
/* other terminal symbols */
3333
TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
3434
TK_SHL, TK_SHR,

lopcodes.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Opcodes for Lua virtual machine
44
** See Copyright Notice in lua.h
55
*/
@@ -79,6 +79,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
7979
"GEI",
8080
"TEST",
8181
"TESTSET",
82+
"UNDEF",
83+
"ISDEF",
8284
"CALL",
8385
"TAILCALL",
8486
"RETURN",
@@ -162,6 +164,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
162164
,opmode(0, 0, 1, 0, iABC) /* OP_GEI */
163165
,opmode(0, 0, 1, 0, iABC) /* OP_TEST */
164166
,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 */
165169
,opmode(1, 1, 0, 1, iABC) /* OP_CALL */
166170
,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */
167171
,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */

lopcodes.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Opcodes for Lua virtual machine
44
** See Copyright Notice in lua.h
55
*/
@@ -266,6 +266,9 @@ OP_GEI,/* A sB if ((R(A) >= sB) ~= k) then pc++ */
266266
OP_TEST,/* A if (not R(A) == k) then pc++ */
267267
OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */
268268

269+
OP_UNDEF,/* A B R(A)[R(B)] = undef */
270+
OP_ISDEF,/* A B C R(A) = (R(B)[R(C)] == undef */
271+
269272
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
270273
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
271274

lparser.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Lua Parser
44
** See Copyright Notice in lua.h
55
*/
@@ -65,13 +65,6 @@ static void statement (LexState *ls);
6565
static void expr (LexState *ls, expdesc *v);
6666

6767

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-
7568
static l_noret error_expected (LexState *ls, int token) {
7669
luaX_syntaxerror(ls,
7770
luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token)));
@@ -347,7 +340,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) {
347340
const char *msg = luaO_pushfstring(ls->L,
348341
"<goto %s> at line %d jumps into the scope of local '%s'",
349342
getstr(gt->name), gt->line, getstr(vname));
350-
semerror(ls, msg);
343+
luaK_semerror(ls, msg);
351344
}
352345
luaK_patchgoto(fs, gt->pc, label->pc, 1);
353346
/* remove goto from pending list */
@@ -477,7 +470,7 @@ static void fixbreaks (FuncState *fs, BlockCnt *bl) {
477470
static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
478471
const char *msg = "no visible label '%s' for <goto> at line %d";
479472
msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
480-
semerror(ls, msg);
473+
luaK_semerror(ls, msg);
481474
}
482475

483476

@@ -900,6 +893,11 @@ static void primaryexp (LexState *ls, expdesc *v) {
900893
singlevar(ls, v);
901894
return;
902895
}
896+
case TK_UNDEF: {
897+
luaX_next(ls);
898+
init_exp(v, VUNDEF, 0);
899+
return;
900+
}
903901
default: {
904902
luaX_syntaxerror(ls, "unexpected symbol");
905903
}
@@ -1185,6 +1183,10 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
11851183
else { /* assignment -> '=' explist */
11861184
int nexps;
11871185
checknext(ls, '=');
1186+
if (nvars == 1 && testnext(ls, TK_UNDEF)) {
1187+
luaK_codeundef(ls->fs, &lh->v);
1188+
return;
1189+
}
11881190
nexps = explist(ls, &e);
11891191
if (nexps != nvars)
11901192
adjust_assign(ls, nvars, nexps, &e);
@@ -1237,7 +1239,7 @@ static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
12371239
const char *msg = luaO_pushfstring(fs->ls->L,
12381240
"label '%s' already defined on line %d",
12391241
getstr(label), ll->arr[i].line);
1240-
semerror(fs->ls, msg);
1242+
luaK_semerror(fs->ls, msg);
12411243
}
12421244
}
12431245
}
@@ -1650,6 +1652,11 @@ static void statement (LexState *ls) {
16501652
luaX_next(ls); /* skip LOCAL */
16511653
if (testnext(ls, TK_FUNCTION)) /* local function? */
16521654
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 */
16531660
else
16541661
localstat(ls);
16551662
break;

lparser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
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 $
33
** Lua Parser
44
** See Copyright Notice in lua.h
55
*/
@@ -52,7 +52,8 @@ typedef enum {
5252
VRELOC, /* expression can put result in any register;
5353
info = instruction pc */
5454
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" */
5657
} expkind;
5758

5859

0 commit comments

Comments
 (0)