Support for three-token characters (**=, >>=, <<=) which was written by
Michael Hudson, and support in general for the augmented assignment syntax. The graminit.c patch is large!
This commit is contained in:
parent
dd8dbdb717
commit
434d0828d8
|
@ -38,8 +38,9 @@ stmt: simple_stmt | compound_stmt
|
|||
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
|
||||
#small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt
|
||||
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt
|
||||
expr_stmt: testlist ('=' testlist)*
|
||||
# For assignments, additional restrictions enforced by the interpreter
|
||||
expr_stmt: testlist (augassign testlist | ('=' testlist)*)
|
||||
augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**='
|
||||
# For normal assignments, additional restrictions enforced by the interpreter
|
||||
print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] )
|
||||
del_stmt: 'del' exprlist
|
||||
pass_stmt: 'pass'
|
||||
|
|
|
@ -211,6 +211,18 @@ translabel(grammar *g, label *lb)
|
|||
printf("Unknown OP label %s\n",
|
||||
lb->lb_str);
|
||||
}
|
||||
else if (lb->lb_str[2] && lb->lb_str[3] && lb->lb_str[4] == lb->lb_str[0]) {
|
||||
int type = (int) PyToken_ThreeChars(lb->lb_str[1],
|
||||
lb->lb_str[2],
|
||||
lb->lb_str[3]);
|
||||
if (type != OP) {
|
||||
lb->lb_type = type;
|
||||
lb->lb_str = NULL;
|
||||
}
|
||||
else
|
||||
printf("Unknown OP label %s\n",
|
||||
lb->lb_str);
|
||||
}
|
||||
else
|
||||
printf("Can't translate STRING label %s\n",
|
||||
lb->lb_str);
|
||||
|
|
|
@ -78,6 +78,17 @@ char *_PyParser_TokenNames[] = {
|
|||
"LEFTSHIFT",
|
||||
"RIGHTSHIFT",
|
||||
"DOUBLESTAR",
|
||||
"PLUSEQUAL",
|
||||
"MINEQUAL",
|
||||
"STAREQUAL",
|
||||
"SLASHEQUAL",
|
||||
"PERCENTEQUAL",
|
||||
"AMPEREQUAL",
|
||||
"VBAREQUAL",
|
||||
"CIRCUMFLEXEQUAL",
|
||||
"LEFTSHIFTEQUAL",
|
||||
"RIGHTSHIFTEQUAL",
|
||||
"DOUBLESTAREQUAL",
|
||||
/* This table must match the #defines in token.h! */
|
||||
"OP",
|
||||
"<ERRORTOKEN>",
|
||||
|
@ -388,15 +399,91 @@ PyToken_TwoChars(int c1, int c2)
|
|||
case '>': return RIGHTSHIFT;
|
||||
}
|
||||
break;
|
||||
case '+':
|
||||
switch (c2) {
|
||||
case '=': return PLUSEQUAL;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
switch (c2) {
|
||||
case '=': return MINEQUAL;
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
switch (c2) {
|
||||
case '*': return DOUBLESTAR;
|
||||
case '=': return STAREQUAL;
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
switch (c2) {
|
||||
case '=': return SLASHEQUAL;
|
||||
}
|
||||
break;
|
||||
case '|':
|
||||
switch (c2) {
|
||||
case '=': return VBAREQUAL;
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
switch (c2) {
|
||||
case '=': return PERCENTEQUAL;
|
||||
}
|
||||
break;
|
||||
case '&':
|
||||
switch (c2) {
|
||||
case '=': return AMPEREQUAL;
|
||||
}
|
||||
break;
|
||||
case '^':
|
||||
switch (c2) {
|
||||
case '=': return CIRCUMFLEXEQUAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return OP;
|
||||
}
|
||||
|
||||
int
|
||||
PyToken_ThreeChars(int c1, int c2, int c3)
|
||||
{
|
||||
switch (c1) {
|
||||
case '<':
|
||||
switch (c2) {
|
||||
case '<':
|
||||
switch (c3) {
|
||||
case '=':
|
||||
return LEFTSHIFTEQUAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
switch (c2) {
|
||||
case '>':
|
||||
switch (c3) {
|
||||
case '=':
|
||||
return RIGHTSHIFTEQUAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
switch (c2) {
|
||||
case '*':
|
||||
switch (c3) {
|
||||
case '=':
|
||||
return DOUBLESTAREQUAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return OP;
|
||||
}
|
||||
|
||||
static int
|
||||
indenterror(struct tok_state *tok)
|
||||
|
@ -770,6 +857,13 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
|
|||
int c2 = tok_nextc(tok);
|
||||
int token = PyToken_TwoChars(c, c2);
|
||||
if (token != OP) {
|
||||
int c3 = tok_nextc(tok);
|
||||
int token3 = PyToken_ThreeChars(c, c2, c3);
|
||||
if (token3 != OP) {
|
||||
token = token3;
|
||||
} else {
|
||||
tok_backup(tok, c3);
|
||||
}
|
||||
*p_start = tok->start;
|
||||
*p_end = tok->cur;
|
||||
return token;
|
||||
|
|
205
Python/ceval.c
205
Python/ceval.c
|
@ -669,12 +669,69 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
PUSH(w);
|
||||
continue;
|
||||
|
||||
case ROT_FOUR:
|
||||
u = POP();
|
||||
v = POP();
|
||||
w = POP();
|
||||
x = POP();
|
||||
PUSH(u);
|
||||
PUSH(x);
|
||||
PUSH(w);
|
||||
PUSH(v);
|
||||
continue;
|
||||
|
||||
case DUP_TOP:
|
||||
v = TOP();
|
||||
Py_INCREF(v);
|
||||
PUSH(v);
|
||||
continue;
|
||||
|
||||
case DUP_TOPX:
|
||||
switch (oparg) {
|
||||
case 5:
|
||||
case 4:
|
||||
case 3:
|
||||
case 2:
|
||||
case 1:
|
||||
x = POP();
|
||||
if (oparg == 1) break;
|
||||
w = POP();
|
||||
if (oparg == 2) break;
|
||||
v = POP();
|
||||
if (oparg == 3) break;
|
||||
u = POP();
|
||||
if (oparg == 4) break;
|
||||
t = POP();
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid argument to DUP_TOPX: %d!\n", oparg);
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"invalid argument to DUP_TOPX");
|
||||
x = NULL;
|
||||
}
|
||||
if (x == NULL)
|
||||
break;
|
||||
switch (oparg) {
|
||||
case 5: PUSH(t);
|
||||
Py_INCREF(t); /* Fallthrough */
|
||||
case 4: PUSH(u);
|
||||
Py_INCREF(u); /* Fallthrough */
|
||||
case 3: PUSH(v);
|
||||
Py_INCREF(v); /* Fallthrough */
|
||||
case 2: PUSH(w);
|
||||
Py_INCREF(w); /* Fallthrough */
|
||||
case 1: PUSH(x);
|
||||
Py_INCREF(x); /* Fallthrough */
|
||||
}
|
||||
switch (oparg) {
|
||||
case 5: PUSH(t); /* Fallthrough */
|
||||
case 4: PUSH(u); /* Fallthrough */
|
||||
case 3: PUSH(v); /* Fallthrough */
|
||||
case 2: PUSH(w); /* Fallthrough */
|
||||
case 1: PUSH(x); /* Fallthrough */
|
||||
}
|
||||
continue;
|
||||
|
||||
case UNARY_POSITIVE:
|
||||
v = POP();
|
||||
x = PyNumber_Positive(v);
|
||||
|
@ -891,6 +948,146 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_POWER:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlacePower(v, w, Py_None);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_MULTIPLY:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlaceMultiply(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_DIVIDE:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlaceDivide(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_MODULO:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlaceRemainder(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_ADD:
|
||||
w = POP();
|
||||
v = POP();
|
||||
if (PyInt_Check(v) && PyInt_Check(w)) {
|
||||
/* INLINE: int + int */
|
||||
register long a, b, i;
|
||||
a = PyInt_AS_LONG(v);
|
||||
b = PyInt_AS_LONG(w);
|
||||
i = a + b;
|
||||
if ((i^a) < 0 && (i^b) < 0) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"integer addition");
|
||||
x = NULL;
|
||||
}
|
||||
else
|
||||
x = PyInt_FromLong(i);
|
||||
}
|
||||
else
|
||||
x = PyNumber_InPlaceAdd(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_SUBTRACT:
|
||||
w = POP();
|
||||
v = POP();
|
||||
if (PyInt_Check(v) && PyInt_Check(w)) {
|
||||
/* INLINE: int - int */
|
||||
register long a, b, i;
|
||||
a = PyInt_AS_LONG(v);
|
||||
b = PyInt_AS_LONG(w);
|
||||
i = a - b;
|
||||
if ((i^a) < 0 && (i^~b) < 0) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"integer subtraction");
|
||||
x = NULL;
|
||||
}
|
||||
else
|
||||
x = PyInt_FromLong(i);
|
||||
}
|
||||
else
|
||||
x = PyNumber_InPlaceSubtract(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_LSHIFT:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlaceLshift(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_RSHIFT:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlaceRshift(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_AND:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlaceAnd(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_XOR:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlaceXor(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case INPLACE_OR:
|
||||
w = POP();
|
||||
v = POP();
|
||||
x = PyNumber_InPlaceOr(v, w);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case SLICE+0:
|
||||
case SLICE+1:
|
||||
case SLICE+2:
|
||||
|
@ -1063,6 +1260,10 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
stream = NULL;
|
||||
break;
|
||||
|
||||
|
||||
#ifdef CASE_TOO_BIG
|
||||
default: switch (opcode) {
|
||||
#endif
|
||||
case BREAK_LOOP:
|
||||
why = WHY_BREAK;
|
||||
break;
|
||||
|
@ -1180,10 +1381,6 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
PyErr_SetObject(PyExc_NameError, w);
|
||||
break;
|
||||
|
||||
#ifdef CASE_TOO_BIG
|
||||
default: switch (opcode) {
|
||||
#endif
|
||||
|
||||
case UNPACK_SEQUENCE:
|
||||
v = POP();
|
||||
if (PyTuple_Check(v)) {
|
||||
|
|
219
Python/compile.c
219
Python/compile.c
|
@ -391,12 +391,14 @@ static void com_list(struct compiling *, node *, int);
|
|||
static void com_list_iter(struct compiling *, node *, node *, char *);
|
||||
static int com_argdefs(struct compiling *, node *);
|
||||
static int com_newlocal(struct compiling *, char *);
|
||||
static void com_assign(struct compiling *, node *, int);
|
||||
static void com_assign(struct compiling *, node *, int, node *);
|
||||
static void com_assign_name(struct compiling *, node *, int);
|
||||
static PyCodeObject *icompile(struct _node *, struct compiling *);
|
||||
static PyCodeObject *jcompile(struct _node *, char *,
|
||||
struct compiling *);
|
||||
static PyObject *parsestrplus(node *);
|
||||
static PyObject *parsestr(char *);
|
||||
static node *get_rawdocstring(node *);
|
||||
|
||||
static int
|
||||
com_init(struct compiling *c, char *filename)
|
||||
|
@ -995,7 +997,7 @@ com_list_for(struct compiling *c, node *n, node *e, char *t)
|
|||
com_addoparg(c, SET_LINENO, n->n_lineno);
|
||||
com_addfwref(c, FOR_LOOP, &anchor);
|
||||
com_push(c, 1);
|
||||
com_assign(c, CHILD(n, 1), OP_ASSIGN);
|
||||
com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
|
||||
c->c_loops++;
|
||||
com_list_iter(c, n, e, t);
|
||||
c->c_loops--;
|
||||
|
@ -1202,6 +1204,59 @@ com_slice(struct compiling *c, node *n, int op)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
com_augassign_slice(struct compiling *c, node *n, int opcode, node *augn)
|
||||
{
|
||||
if (NCH(n) == 1) {
|
||||
com_addbyte(c, DUP_TOP);
|
||||
com_push(c, 1);
|
||||
com_addbyte(c, SLICE);
|
||||
com_node(c, augn);
|
||||
com_addbyte(c, opcode);
|
||||
com_pop(c, 1);
|
||||
com_addbyte(c, ROT_TWO);
|
||||
com_addbyte(c, STORE_SLICE);
|
||||
com_pop(c, 2);
|
||||
} else if (NCH(n) == 2 && TYPE(CHILD(n, 0)) != COLON) {
|
||||
com_node(c, CHILD(n, 0));
|
||||
com_addoparg(c, DUP_TOPX, 2);
|
||||
com_push(c, 2);
|
||||
com_addbyte(c, SLICE+1);
|
||||
com_pop(c, 1);
|
||||
com_node(c, augn);
|
||||
com_addbyte(c, opcode);
|
||||
com_pop(c, 1);
|
||||
com_addbyte(c, ROT_THREE);
|
||||
com_addbyte(c, STORE_SLICE+1);
|
||||
com_pop(c, 3);
|
||||
} else if (NCH(n) == 2) {
|
||||
com_node(c, CHILD(n, 1));
|
||||
com_addoparg(c, DUP_TOPX, 2);
|
||||
com_push(c, 2);
|
||||
com_addbyte(c, SLICE+2);
|
||||
com_pop(c, 1);
|
||||
com_node(c, augn);
|
||||
com_addbyte(c, opcode);
|
||||
com_pop(c, 1);
|
||||
com_addbyte(c, ROT_THREE);
|
||||
com_addbyte(c, STORE_SLICE+2);
|
||||
com_pop(c, 3);
|
||||
} else {
|
||||
com_node(c, CHILD(n, 0));
|
||||
com_node(c, CHILD(n, 2));
|
||||
com_addoparg(c, DUP_TOPX, 3);
|
||||
com_push(c, 3);
|
||||
com_addbyte(c, SLICE+3);
|
||||
com_pop(c, 2);
|
||||
com_node(c, augn);
|
||||
com_addbyte(c, opcode);
|
||||
com_pop(c, 1);
|
||||
com_addbyte(c, ROT_FOUR);
|
||||
com_addbyte(c, STORE_SLICE+3);
|
||||
com_pop(c, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
com_argument(struct compiling *c, node *n, PyObject **pkeywords)
|
||||
{
|
||||
|
@ -1376,7 +1431,7 @@ com_subscript(struct compiling *c, node *n)
|
|||
}
|
||||
|
||||
static void
|
||||
com_subscriptlist(struct compiling *c, node *n, int assigning)
|
||||
com_subscriptlist(struct compiling *c, node *n, int assigning, node *augn)
|
||||
{
|
||||
int i, op;
|
||||
REQ(n, subscriptlist);
|
||||
|
@ -1388,11 +1443,20 @@ com_subscriptlist(struct compiling *c, node *n, int assigning)
|
|||
|| (NCH(sub) > 1 && TYPE(CHILD(sub, 1)) == COLON))
|
||||
&& (TYPE(CHILD(sub,NCH(sub)-1)) != sliceop))
|
||||
{
|
||||
if (assigning == OP_APPLY)
|
||||
switch (assigning) {
|
||||
case OP_DELETE:
|
||||
op = DELETE_SLICE;
|
||||
break;
|
||||
case OP_ASSIGN:
|
||||
op = STORE_SLICE;
|
||||
break;
|
||||
case OP_APPLY:
|
||||
op = SLICE;
|
||||
else
|
||||
op = ((assigning == OP_ASSIGN) ?
|
||||
STORE_SLICE : DELETE_SLICE);
|
||||
break;
|
||||
default:
|
||||
com_augassign_slice(c, sub, assigning, augn);
|
||||
return;
|
||||
}
|
||||
com_slice(c, sub, op);
|
||||
if (op == STORE_SLICE)
|
||||
com_pop(c, 2);
|
||||
|
@ -1410,17 +1474,30 @@ com_subscriptlist(struct compiling *c, node *n, int assigning)
|
|||
com_addoparg(c, BUILD_TUPLE, i);
|
||||
com_pop(c, i-1);
|
||||
}
|
||||
if (assigning == OP_APPLY) {
|
||||
op = BINARY_SUBSCR;
|
||||
i = 1;
|
||||
}
|
||||
else if (assigning == OP_ASSIGN) {
|
||||
op = STORE_SUBSCR;
|
||||
i = 3;
|
||||
}
|
||||
else {
|
||||
switch (assigning) {
|
||||
case OP_DELETE:
|
||||
op = DELETE_SUBSCR;
|
||||
i = 2;
|
||||
break;
|
||||
default:
|
||||
case OP_ASSIGN:
|
||||
op = STORE_SUBSCR;
|
||||
i = 3;
|
||||
break;
|
||||
case OP_APPLY:
|
||||
op = BINARY_SUBSCR;
|
||||
i = 1;
|
||||
break;
|
||||
}
|
||||
if (assigning > OP_APPLY) {
|
||||
com_addoparg(c, DUP_TOPX, 2);
|
||||
com_push(c, 2);
|
||||
com_addbyte(c, BINARY_SUBSCR);
|
||||
com_pop(c, 1);
|
||||
com_node(c, augn);
|
||||
com_addbyte(c, assigning);
|
||||
com_pop(c, 1);
|
||||
com_addbyte(c, ROT_THREE);
|
||||
}
|
||||
com_addbyte(c, op);
|
||||
com_pop(c, i);
|
||||
|
@ -1438,7 +1515,7 @@ com_apply_trailer(struct compiling *c, node *n)
|
|||
com_select_member(c, CHILD(n, 1));
|
||||
break;
|
||||
case LSQB:
|
||||
com_subscriptlist(c, CHILD(n, 1), OP_APPLY);
|
||||
com_subscriptlist(c, CHILD(n, 1), OP_APPLY, NULL);
|
||||
break;
|
||||
default:
|
||||
com_error(c, PyExc_SystemError,
|
||||
|
@ -1832,8 +1909,21 @@ com_list(struct compiling *c, node *n, int toplevel)
|
|||
|
||||
/* Begin of assignment compilation */
|
||||
|
||||
static void com_assign_name(struct compiling *, node *, int);
|
||||
static void com_assign(struct compiling *, node *, int);
|
||||
|
||||
static void
|
||||
com_augassign_attr(struct compiling *c, node *n, int opcode, node *augn)
|
||||
{
|
||||
com_addbyte(c, DUP_TOP);
|
||||
com_push(c, 1);
|
||||
com_addopname(c, LOAD_ATTR, n);
|
||||
com_pop(c, 1);
|
||||
com_node(c, augn);
|
||||
com_addbyte(c, opcode);
|
||||
com_pop(c, 1);
|
||||
com_addbyte(c, ROT_TWO);
|
||||
com_addopname(c, STORE_ATTR, n);
|
||||
com_pop(c, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
com_assign_attr(struct compiling *c, node *n, int assigning)
|
||||
|
@ -1843,7 +1933,7 @@ com_assign_attr(struct compiling *c, node *n, int assigning)
|
|||
}
|
||||
|
||||
static void
|
||||
com_assign_trailer(struct compiling *c, node *n, int assigning)
|
||||
com_assign_trailer(struct compiling *c, node *n, int assigning, node *augn)
|
||||
{
|
||||
REQ(n, trailer);
|
||||
switch (TYPE(CHILD(n, 0))) {
|
||||
|
@ -1852,10 +1942,13 @@ com_assign_trailer(struct compiling *c, node *n, int assigning)
|
|||
"can't assign to function call");
|
||||
break;
|
||||
case DOT: /* '.' NAME */
|
||||
if (assigning > OP_APPLY)
|
||||
com_augassign_attr(c, CHILD(n, 1), assigning, augn);
|
||||
else
|
||||
com_assign_attr(c, CHILD(n, 1), assigning);
|
||||
break;
|
||||
case LSQB: /* '[' subscriptlist ']' */
|
||||
com_subscriptlist(c, CHILD(n, 1), assigning);
|
||||
com_subscriptlist(c, CHILD(n, 1), assigning, augn);
|
||||
break;
|
||||
default:
|
||||
com_error(c, PyExc_SystemError, "unknown trailer type");
|
||||
|
@ -1874,7 +1967,19 @@ com_assign_sequence(struct compiling *c, node *n, int assigning)
|
|||
com_push(c, i-1);
|
||||
}
|
||||
for (i = 0; i < NCH(n); i += 2)
|
||||
com_assign(c, CHILD(n, i), assigning);
|
||||
com_assign(c, CHILD(n, i), assigning, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
com_augassign_name(struct compiling *c, node *n, int opcode, node *augn)
|
||||
{
|
||||
REQ(n, NAME);
|
||||
com_addopname(c, LOAD_NAME, n);
|
||||
com_push(c, 1);
|
||||
com_node(c, augn);
|
||||
com_addbyte(c, opcode);
|
||||
com_pop(c, 1);
|
||||
com_assign_name(c, n, OP_ASSIGN);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1887,7 +1992,7 @@ com_assign_name(struct compiling *c, node *n, int assigning)
|
|||
}
|
||||
|
||||
static void
|
||||
com_assign(struct compiling *c, node *n, int assigning)
|
||||
com_assign(struct compiling *c, node *n, int assigning, node *augn)
|
||||
{
|
||||
/* Loop to avoid trivial recursion */
|
||||
for (;;) {
|
||||
|
@ -1896,6 +2001,11 @@ com_assign(struct compiling *c, node *n, int assigning)
|
|||
case exprlist:
|
||||
case testlist:
|
||||
if (NCH(n) > 1) {
|
||||
if (assigning > OP_APPLY) {
|
||||
com_error(c, PyExc_SyntaxError,
|
||||
"augmented assign to tuple not possible");
|
||||
return;
|
||||
}
|
||||
com_assign_sequence(c, n, assigning);
|
||||
return;
|
||||
}
|
||||
|
@ -1940,7 +2050,7 @@ com_assign(struct compiling *c, node *n, int assigning)
|
|||
com_apply_trailer(c, CHILD(n, i));
|
||||
} /* NB i is still alive */
|
||||
com_assign_trailer(c,
|
||||
CHILD(n, i), assigning);
|
||||
CHILD(n, i), assigning, augn);
|
||||
return;
|
||||
}
|
||||
n = CHILD(n, 0);
|
||||
|
@ -1956,6 +2066,11 @@ com_assign(struct compiling *c, node *n, int assigning)
|
|||
"can't assign to ()");
|
||||
return;
|
||||
}
|
||||
if (assigning > OP_APPLY) {
|
||||
com_error(c, PyExc_SyntaxError,
|
||||
"augmented assign to tuple not possible");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case LSQB:
|
||||
n = CHILD(n, 1);
|
||||
|
@ -1964,10 +2079,20 @@ com_assign(struct compiling *c, node *n, int assigning)
|
|||
"can't assign to []");
|
||||
return;
|
||||
}
|
||||
if (assigning > OP_APPLY) {
|
||||
com_error(c, PyExc_SyntaxError,
|
||||
"augmented assign to list not possible");
|
||||
return;
|
||||
}
|
||||
com_assign_sequence(c, n, assigning);
|
||||
return;
|
||||
case NAME:
|
||||
com_assign_name(c, CHILD(n, 0), assigning);
|
||||
if (assigning > OP_APPLY)
|
||||
com_augassign_name(c, CHILD(n, 0),
|
||||
assigning, augn);
|
||||
else
|
||||
com_assign_name(c, CHILD(n, 0),
|
||||
assigning);
|
||||
return;
|
||||
default:
|
||||
com_error(c, PyExc_SyntaxError,
|
||||
|
@ -1991,31 +2116,61 @@ com_assign(struct compiling *c, node *n, int assigning)
|
|||
}
|
||||
}
|
||||
|
||||
/* Forward */ static node *get_rawdocstring(node *);
|
||||
static void
|
||||
com_augassign(struct compiling *c, node *n)
|
||||
{
|
||||
int opcode;
|
||||
|
||||
switch (STR(CHILD(CHILD(n, 1), 0))[0]) {
|
||||
case '+': opcode = INPLACE_ADD; break;
|
||||
case '-': opcode = INPLACE_SUBTRACT; break;
|
||||
case '/': opcode = INPLACE_DIVIDE; break;
|
||||
case '%': opcode = INPLACE_MODULO; break;
|
||||
case '<': opcode = INPLACE_LSHIFT; break;
|
||||
case '>': opcode = INPLACE_RSHIFT; break;
|
||||
case '&': opcode = INPLACE_AND; break;
|
||||
case '^': opcode = INPLACE_XOR; break;
|
||||
case '|': opcode = INPLACE_OR; break;
|
||||
case '*':
|
||||
if (STR(CHILD(CHILD(n, 1), 0))[1] == '*')
|
||||
opcode = INPLACE_POWER;
|
||||
else
|
||||
opcode = INPLACE_MULTIPLY;
|
||||
break;
|
||||
default:
|
||||
com_error(c, PyExc_SystemError, "com_augassign: bad operator");
|
||||
return;
|
||||
}
|
||||
com_assign(c, CHILD(n, 0), opcode, CHILD(n, 2));
|
||||
}
|
||||
|
||||
static void
|
||||
com_expr_stmt(struct compiling *c, node *n)
|
||||
{
|
||||
REQ(n, expr_stmt); /* testlist ('=' testlist)* */
|
||||
REQ(n, expr_stmt);
|
||||
/* testlist (('=' testlist)* | augassign testlist) */
|
||||
/* Forget it if we have just a doc string here */
|
||||
if (!c->c_interactive && NCH(n) == 1 && get_rawdocstring(n) != NULL)
|
||||
return;
|
||||
com_node(c, CHILD(n, NCH(n)-1));
|
||||
if (NCH(n) == 1) {
|
||||
com_node(c, CHILD(n, NCH(n)-1));
|
||||
if (c->c_interactive)
|
||||
com_addbyte(c, PRINT_EXPR);
|
||||
else
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
else if (TYPE(CHILD(n,1)) == augassign)
|
||||
com_augassign(c, n);
|
||||
else {
|
||||
int i;
|
||||
com_node(c, CHILD(n, NCH(n)-1));
|
||||
for (i = 0; i < NCH(n)-2; i+=2) {
|
||||
if (i+2 < NCH(n)-2) {
|
||||
com_addbyte(c, DUP_TOP);
|
||||
com_push(c, 1);
|
||||
}
|
||||
com_assign(c, CHILD(n, i), OP_ASSIGN);
|
||||
com_assign(c, CHILD(n, i), OP_ASSIGN, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2472,7 +2627,7 @@ com_for_stmt(struct compiling *c, node *n)
|
|||
com_addoparg(c, SET_LINENO, n->n_lineno);
|
||||
com_addfwref(c, FOR_LOOP, &anchor);
|
||||
com_push(c, 1);
|
||||
com_assign(c, CHILD(n, 1), OP_ASSIGN);
|
||||
com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
|
||||
c->c_loops++;
|
||||
com_node(c, CHILD(n, 5));
|
||||
c->c_loops--;
|
||||
|
@ -2594,7 +2749,7 @@ com_try_except(struct compiling *c, node *n)
|
|||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
if (NCH(ch) > 3)
|
||||
com_assign(c, CHILD(ch, 3), OP_ASSIGN);
|
||||
com_assign(c, CHILD(ch, 3), OP_ASSIGN, NULL);
|
||||
else {
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
|
@ -2940,7 +3095,7 @@ com_node(struct compiling *c, node *n)
|
|||
com_print_stmt(c, n);
|
||||
break;
|
||||
case del_stmt: /* 'del' exprlist */
|
||||
com_assign(c, CHILD(n, 1), OP_DELETE);
|
||||
com_assign(c, CHILD(n, 1), OP_DELETE, NULL);
|
||||
break;
|
||||
case pass_stmt:
|
||||
break;
|
||||
|
|
1748
Python/graminit.c
1748
Python/graminit.c
File diff suppressed because it is too large
Load Diff
|
@ -66,7 +66,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
|
|||
/* XXX Perhaps the magic number should be frozen and a version field
|
||||
added to the .pyc file header? */
|
||||
/* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */
|
||||
#define MAGIC (50821 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||
#define MAGIC (50822 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||
|
||||
/* Magic word as global; note that _PyImport_Init() can change the
|
||||
value of this global to accommodate for alterations of how the
|
||||
|
|
Loading…
Reference in New Issue