diff -urN lua-5.1-work6/src/llex.c lua-5.1-work6_sh/src/llex.c
--- lua-5.1-work6/src/llex.c 2005-05-17 15:49:15.000000000 -0400
+++ lua-5.1-work6_sh/src/llex.c 2005-06-23 14:20:38.000000000 -0400
@@ -38,7 +38,7 @@
"in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while",
"..", "...", "==", ">=", "<=", "~=",
- "<number>", "<name>", "<string>", "<eof>",
+ "<number>", "<name>", "<string>", "<eof>", ":=",
NULL
};
@@ -368,6 +368,11 @@
if (ls->current != '=') return '~';
else { next(ls); return TK_NE; }
}
+ case ':': {
+ next(ls);
+ if (ls->current != '=') return ':';
+ else { next(ls); return TK_MUTATE_ASN; }
+ }
case '"':
case '\'': {
read_string(ls, ls->current, seminfo);
diff -urN lua-5.1-work6/src/llex.h lua-5.1-work6_sh/src/llex.h
--- lua-5.1-work6/src/llex.h 2005-04-25 15:24:10.000000000 -0400
+++ lua-5.1-work6_sh/src/llex.h 2005-06-23 14:20:37.000000000 -0400
@@ -29,7 +29,7 @@
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
/* other terminal symbols */
TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
- TK_NAME, TK_STRING, TK_EOS
+ TK_NAME, TK_STRING, TK_EOS, TK_MUTATE_ASN
};
/* number of reserved words */
diff -urN lua-5.1-work6/src/lopcodes.c lua-5.1-work6_sh/src/lopcodes.c
--- lua-5.1-work6/src/lopcodes.c 2005-05-04 16:42:28.000000000 -0400
+++ lua-5.1-work6_sh/src/lopcodes.c 2005-06-23 14:20:38.000000000 -0400
@@ -53,6 +53,7 @@
"CLOSE",
"CLOSURE",
"VARARG",
+ "MUTATE",
NULL
};
@@ -98,5 +99,6 @@
,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
+ ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_MUTATE */
};
diff -urN lua-5.1-work6/src/lopcodes.h lua-5.1-work6_sh/src/lopcodes.h
--- lua-5.1-work6/src/lopcodes.h 2005-05-04 16:42:28.000000000 -0400
+++ lua-5.1-work6_sh/src/lopcodes.h 2005-06-23 14:20:37.000000000 -0400
@@ -203,11 +203,12 @@
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
-OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
+OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
+OP_MUTATE/* A B R(A+1) := R(A); R(A) := tm B of R(A) */
} OpCode;
-#define NUM_OPCODES (cast(int, OP_VARARG+1))
+#define NUM_OPCODES (cast(int, OP_MUTATE+1))
diff -urN lua-5.1-work6/src/lparser.c lua-5.1-work6_sh/src/lparser.c
--- lua-5.1-work6/src/lparser.c 2005-05-17 15:49:15.000000000 -0400
+++ lua-5.1-work6_sh/src/lparser.c 2005-06-23 14:20:38.000000000 -0400
@@ -973,6 +973,46 @@
}
+
+static int mutate (LexState *ls, expdesc *v) {
+ /* mutate -> explist */
+ FuncState *fs = ls->fs;
+ int nparams;
+ expdesc args;
+ TMS tm;
+ /* check if we have one of our known mutate operators */
+ switch (ls->t.token) {
+ case TK_MUTATE_ASN:
+ tm = TM_MUTATE_ASN;
+ break;
+ default: /* next token is not for us */
+ return 0;
+ }
+ /* consume the token and make sure the lhs is valid for mutation */
+ next(ls);
+ check_condition(ls, (VLOCAL <= v->k && v->k <= VINDEXED) ||
+ (v->k == VCALL), "syntax error");
+ luaK_exp2nextreg(fs, v);
+ /* find the associated mutate tm and dump it in a register */
+ luaK_codeABC(fs, OP_MUTATE, v->info, tm, 0);
+ luaK_reserveregs(fs, 1);
+ explist1(ls, &args);
+ luaK_setmultret(fs, &args);
+ lua_assert(f->k == VNONRELOC);
+ if (hasmultret(args.k))
+ nparams = LUA_MULTRET;
+ else {
+ luaK_exp2nextreg(fs, &args);
+ nparams = fs->freereg - (v->info + 1);
+ }
+ /* call the tm with the first parameter as the lhs of the mutate */
+ luaK_codeABC(fs, OP_CALL, v->info, nparams+1, 1);
+ fs->freereg = v->info;
+ return 1; /* we handled the expression */
+}
+
+
+
static int cond (LexState *ls) {
/* cond -> exp */
expdesc v;
@@ -1243,15 +1283,17 @@
static void exprstat (LexState *ls) {
- /* stat -> func | assignment */
+ /* stat -> func | assignment | mutate */
FuncState *fs = ls->fs;
struct LHS_assign v;
primaryexp(ls, &v.v);
- if (v.v.k == VCALL) /* stat -> func */
- SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
- else { /* stat -> assignment */
- v.prev = NULL;
- assignment(ls, &v, 1);
+ if (!mutate(ls, &v.v)) { /* stat -> mutate */
+ if (v.v.k == VCALL) /* stat -> func */
+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
+ else { /* stat -> assignment */
+ v.prev = NULL;
+ assignment(ls, &v, 1);
+ }
}
}
diff -urN lua-5.1-work6/src/ltm.c lua-5.1-work6_sh/src/ltm.c
--- lua-5.1-work6/src/ltm.c 2005-05-05 11:34:03.000000000 -0400
+++ lua-5.1-work6_sh/src/ltm.c 2005-06-23 14:20:38.000000000 -0400
@@ -33,7 +33,7 @@
"__gc", "__mode", "__eq",
"__add", "__sub", "__mul", "__div", "__mod",
"__pow", "__unm", "__siz", "__lt", "__le",
- "__concat", "__call"
+ "__concat", "__call", "__mutate_asn"
};
int i;
for (i=0; i<TM_N; i++) {
diff -urN lua-5.1-work6/src/ltm.h lua-5.1-work6_sh/src/ltm.h
--- lua-5.1-work6/src/ltm.h 2005-05-05 11:34:03.000000000 -0400
+++ lua-5.1-work6_sh/src/ltm.h 2005-06-23 14:20:37.000000000 -0400
@@ -33,6 +33,7 @@
TM_LE,
TM_CONCAT,
TM_CALL,
+ TM_MUTATE_ASN,
TM_N /* number of elements in the enum */
} TMS;
diff -urN lua-5.1-work6/src/lvm.c lua-5.1-work6_sh/src/lvm.c
--- lua-5.1-work6/src/lvm.c 2005-05-17 15:49:15.000000000 -0400
+++ lua-5.1-work6_sh/src/lvm.c 2005-06-23 14:20:38.000000000 -0400
@@ -444,6 +444,14 @@
Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
continue;
}
+ case OP_MUTATE: {
+ const TValue *tm = luaT_gettmbyobj(L, ra, GETARG_B(i));
+ if (!ttisfunction(tm))
+ luaG_typeerror(L, ra, "mutate");
+ setobjs2s(L, ra+1, ra);
+ setobj2s(L, ra, tm);
+ continue;
+ }
case OP_NEWTABLE: {
int b = GETARG_B(i);
int c = GETARG_C(i);