📄 compile.c
字号:
node *m;
REQ(n, argument); /* [test '='] test; really [keyword '='] test */
if (NCH(n) == 1) {
if (*pkeywords != NULL) {
com_error(c, PyExc_SyntaxError,
"non-keyword arg after keyword arg");
}
else {
com_node(c, CHILD(n, 0));
}
return;
}
m = n;
do {
m = CHILD(m, 0);
} while (NCH(m) == 1);
if (TYPE(m) != NAME) {
/* f(lambda x: x[0] = 3) ends up getting parsed with
* LHS test = lambda x: x[0], and RHS test = 3.
* SF bug 132313 points out that complaining about a keyword
* then is very confusing.
*/
com_error(c, PyExc_SyntaxError,
TYPE(m) == lambdef ?
"lambda cannot contain assignment" :
"keyword can't be an expression");
}
else {
PyObject *v = PyString_InternFromString(STR(m));
if (v != NULL && *pkeywords == NULL)
*pkeywords = PyDict_New();
if (v == NULL)
c->c_errors++;
else if (*pkeywords == NULL) {
c->c_errors++;
Py_DECREF(v);
} else {
if (PyDict_GetItem(*pkeywords, v) != NULL)
com_error(c, PyExc_SyntaxError,
"duplicate keyword argument");
else
if (PyDict_SetItem(*pkeywords, v, v) != 0)
c->c_errors++;
com_addoparg(c, LOAD_CONST, com_addconst(c, v));
com_push(c, 1);
Py_DECREF(v);
}
}
com_node(c, CHILD(n, 2));
}
static void
com_call_function(struct compiling *c, node *n)
{
if (TYPE(n) == RPAR) {
com_addoparg(c, CALL_FUNCTION, 0);
}
else {
PyObject *keywords = NULL;
int i, na, nk;
int lineno = n->n_lineno;
int star_flag = 0;
int starstar_flag = 0;
int opcode;
REQ(n, arglist);
na = 0;
nk = 0;
for (i = 0; i < NCH(n); i += 2) {
node *ch = CHILD(n, i);
if (TYPE(ch) == STAR ||
TYPE(ch) == DOUBLESTAR)
break;
if (ch->n_lineno != lineno) {
lineno = ch->n_lineno;
com_addoparg(c, SET_LINENO, lineno);
}
com_argument(c, ch, &keywords);
if (keywords == NULL)
na++;
else
nk++;
}
Py_XDECREF(keywords);
while (i < NCH(n)) {
node *tok = CHILD(n, i);
node *ch = CHILD(n, i+1);
i += 3;
switch (TYPE(tok)) {
case STAR: star_flag = 1; break;
case DOUBLESTAR: starstar_flag = 1; break;
}
com_node(c, ch);
}
if (na > 255 || nk > 255) {
com_error(c, PyExc_SyntaxError,
"more than 255 arguments");
}
if (star_flag || starstar_flag)
opcode = CALL_FUNCTION_VAR - 1 +
star_flag + (starstar_flag << 1);
else
opcode = CALL_FUNCTION;
com_addoparg(c, opcode, na | (nk << 8));
com_pop(c, na + 2*nk + star_flag + starstar_flag);
}
}
static void
com_select_member(struct compiling *c, node *n)
{
com_addopname(c, LOAD_ATTR, n);
}
static void
com_sliceobj(struct compiling *c, node *n)
{
int i=0;
int ns=2; /* number of slice arguments */
node *ch;
/* first argument */
if (TYPE(CHILD(n,i)) == COLON) {
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_push(c, 1);
i++;
}
else {
com_node(c, CHILD(n,i));
i++;
REQ(CHILD(n,i),COLON);
i++;
}
/* second argument */
if (i < NCH(n) && TYPE(CHILD(n,i)) == test) {
com_node(c, CHILD(n,i));
i++;
}
else {
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_push(c, 1);
}
/* remaining arguments */
for (; i < NCH(n); i++) {
ns++;
ch=CHILD(n,i);
REQ(ch, sliceop);
if (NCH(ch) == 1) {
/* right argument of ':' missing */
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_push(c, 1);
}
else
com_node(c, CHILD(ch,1));
}
com_addoparg(c, BUILD_SLICE, ns);
com_pop(c, 1 + (ns == 3));
}
static void
com_subscript(struct compiling *c, node *n)
{
node *ch;
REQ(n, subscript);
ch = CHILD(n,0);
/* check for rubber index */
if (TYPE(ch) == DOT && TYPE(CHILD(n,1)) == DOT) {
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_Ellipsis));
com_push(c, 1);
}
else {
/* check for slice */
if ((TYPE(ch) == COLON || NCH(n) > 1))
com_sliceobj(c, n);
else {
REQ(ch, test);
com_node(c, ch);
}
}
}
static void
com_subscriptlist(struct compiling *c, node *n, int assigning, node *augn)
{
int i, op;
REQ(n, subscriptlist);
/* Check to make backward compatible slice behavior for '[i:j]' */
if (NCH(n) == 1) {
node *sub = CHILD(n, 0); /* subscript */
/* 'Basic' slice, should have exactly one colon. */
if ((TYPE(CHILD(sub, 0)) == COLON
|| (NCH(sub) > 1 && TYPE(CHILD(sub, 1)) == COLON))
&& (TYPE(CHILD(sub,NCH(sub)-1)) != sliceop))
{
switch (assigning) {
case OP_DELETE:
op = DELETE_SLICE;
break;
case OP_ASSIGN:
op = STORE_SLICE;
break;
case OP_APPLY:
op = SLICE;
break;
default:
com_augassign_slice(c, sub, assigning, augn);
return;
}
com_slice(c, sub, op);
if (op == STORE_SLICE)
com_pop(c, 2);
else if (op == DELETE_SLICE)
com_pop(c, 1);
return;
}
}
/* Else normal subscriptlist. Compile each subscript. */
for (i = 0; i < NCH(n); i += 2)
com_subscript(c, CHILD(n, i));
/* Put multiple subscripts into a tuple */
if (NCH(n) > 1) {
i = (NCH(n)+1) / 2;
com_addoparg(c, BUILD_TUPLE, i);
com_pop(c, i-1);
}
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);
}
static void
com_apply_trailer(struct compiling *c, node *n)
{
REQ(n, trailer);
switch (TYPE(CHILD(n, 0))) {
case LPAR:
com_call_function(c, CHILD(n, 1));
break;
case DOT:
com_select_member(c, CHILD(n, 1));
break;
case LSQB:
com_subscriptlist(c, CHILD(n, 1), OP_APPLY, NULL);
break;
default:
com_error(c, PyExc_SystemError,
"com_apply_trailer: unknown trailer type");
}
}
static void
com_power(struct compiling *c, node *n)
{
int i;
REQ(n, power);
com_atom(c, CHILD(n, 0));
for (i = 1; i < NCH(n); i++) {
if (TYPE(CHILD(n, i)) == DOUBLESTAR) {
com_factor(c, CHILD(n, i+1));
com_addbyte(c, BINARY_POWER);
com_pop(c, 1);
break;
}
else
com_apply_trailer(c, CHILD(n, i));
}
}
static void
com_invert_constant(struct compiling *c, node *n)
{
/* Compute the inverse of int and longs and use them directly,
but be prepared to generate code for all other
possibilities (invalid numbers, floats, complex).
*/
PyObject *num, *inv = NULL;
int i;
REQ(n, NUMBER);
num = parsenumber(c, STR(n));
if (num == NULL)
i = 255;
else {
inv = PyNumber_Invert(num);
if (inv == NULL) {
PyErr_Clear();
i = com_addconst(c, num);
} else {
i = com_addconst(c, inv);
Py_DECREF(inv);
}
Py_DECREF(num);
}
com_addoparg(c, LOAD_CONST, i);
com_push(c, 1);
if (num != NULL && inv == NULL)
com_addbyte(c, UNARY_INVERT);
}
static int
is_float_zero(const char *p)
{
int found_radix_point = 0;
int ch;
while ((ch = Py_CHARMASK(*p++)) != '\0') {
switch (ch) {
case '0':
/* no reason to believe it's not 0 -- continue */
break;
case 'e': case 'E': case 'j': case 'J':
/* If this was a hex constant, we already would have
returned 0 due to the 'x' or 'X', so 'e' or 'E'
must be an exponent marker, and we haven't yet
seen a non-zero digit, and it doesn't matter what
the exponent is then. For 'j' or 'J' similarly,
except that this is an imaginary 0 then. */
return 1;
case '.':
found_radix_point = 1;
break;
default:
return 0;
}
}
return found_radix_point;
}
static void
com_factor(struct compiling *c, node *n)
{
int childtype = TYPE(CHILD(n, 0));
node *pfactor, *ppower, *patom, *pnum;
REQ(n, factor);
/* If the unary +, -, or ~ operator is applied to a constant,
don't generate a UNARY_xxx opcode. Just store the
approriate value as a constant. If the value is negative,
extend the string containing the constant and insert a
negative in the 0th position -- unless we're doing unary minus
of a floating zero! In that case the sign is significant, but
the const dict can't distinguish +0.0 from -0.0.
*/
if ((childtype == PLUS || childtype == MINUS || childtype == TILDE)
&& NCH(n) == 2
&& TYPE((pfactor = CHILD(n, 1))) == factor
&& NCH(pfactor) == 1
&& TYPE((ppower = CHILD(pfactor, 0))) == power
&& NCH(ppower) == 1
&& TYPE((patom = CHILD(ppower, 0))) == atom
&& TYPE((pnum = CHILD(patom, 0))) == NUMBER
&& !(childtype == MINUS && is_float_zero(STR(pnum)))) {
if (childtype == TILDE) {
com_invert_constant(c, pnum);
return;
}
if (childtype == MINUS) {
char *s = PyMem_Malloc(strlen(STR(pnum)) + 2);
if (s == NULL) {
com_error(c, PyExc_MemoryError, "");
com_addbyte(c, 255);
return;
}
s[0] = '-';
strcpy(s + 1, STR(pnum));
PyMem_Free(STR(pnum));
STR(pnum) = s;
}
com_atom(c, patom);
}
else if (childtype == PLUS) {
com_factor(c, CHILD(n, 1));
com_addbyte(c, UNARY_POSITIVE);
}
else if (childtype == MINUS) {
com_factor(c, CHILD(n, 1));
com_addbyte(c, UNARY_NEGATIVE);
}
else if (childtype == TILDE) {
com_factor(c, CHILD(n, 1));
com_addbyte(c, UNARY_INVERT);
}
else {
com_power(c, CHILD(n, 0));
}
}
static void
com_term(struct compiling *c, node *n)
{
int i;
int op;
REQ(n, term);
com_factor(c, CHILD(n, 0));
for (i = 2; i < NCH(n); i += 2) {
com_factor(c, CHILD(n, i));
switch (TYPE(CHILD(n, i-1))) {
case STAR:
op = BINARY_MULTIPLY;
break;
case SLASH:
if (c->c_flags & CO_FUTURE_DIVISION)
op = BINARY_TRUE_DIVIDE;
else
op = BINARY_DIVIDE;
break;
case PERCENT:
op = BINARY_MODULO;
break;
case DOUBLESLASH:
op = BINARY_FLOOR_DIVIDE;
break;
default:
com_error(c, PyExc_SystemError,
"com_term: operator not *, /, // or %");
op = 255;
}
com_addbyte(c, op);
com_pop(c, 1);
}
}
static void
com_arith_expr(struct compiling *c, node *n)
{
int i;
int op;
REQ(n, arith_expr);
com_term(c, CHILD(n, 0));
for (i = 2; i < NCH(n); i += 2) {
com_term(c, CHILD(n, i));
switch (TYPE(CHILD(n, i-1))) {
case PLUS:
op = BINARY_ADD;
break;
case MINUS:
op = BINARY_SUBTRACT;
break;
default:
com_error(c, PyExc_SystemError,
"com_arith_expr: operator not + or -");
op = 255;
}
com_addbyte(c, op);
com_pop(c, 1);
}
}
static void
com_shift_expr(struct compiling *c, node *n)
{
int i;
int op;
REQ(n, shift_expr);
com_arith_expr(c, CHILD(n, 0));
for (i = 2; i < NCH(n); i += 2) {
com_arith_expr(c, CHILD(n, i));
switch (TYPE(CHILD(n, i-1))) {
case LEFTSHIFT:
op = BINARY_LSHIFT;
break;
case RIGHTSHIFT:
op = BINARY_RSHIFT;
break;
default:
com_error(c, PyExc_SystemError,
"com_shift_expr: operator not << or >>");
op = 255;
}
com_addbyte(c, op);
com_pop(c, 1);
}
}
static void
com_and_expr(struct compiling *c, node *n)
{
int i;
int op;
REQ(n, and_expr);
com_shift_expr(c, CHILD(n, 0));
for (i = 2; i < NCH(n); i += 2) {
com_shift_expr(c, CHILD(n, i));
if (TYPE(CHILD(n, i-1)) == AMPER) {
op = BINARY_AND;
}
else {
com_error(c, PyExc_SystemError,
"com_and_expr: operator not &");
op = 255;
}
com_addbyte(c, op);
com_pop(c, 1);
}
}
static void
com_xor_expr(struct compiling *c, node *n)
{
int i;
int op;
REQ(n, xor_expr);
com_and_expr(c, CHILD(n, 0));
for (i = 2; i < NCH(n); i += 2) {
com_and_expr(c, CHILD(n, i));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -