summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2001-08-12 01:54:38 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2001-08-12 01:54:38 (GMT)
commitd5e5a2aa284d610b2bf1fb948c0e8da348ad2733 (patch)
tree2d4893c4c38e39d40e35e74dac432896e9e273f6 /Python
parentb5b7b78414e5f1a42ab4205c110626c9cd7a79b9 (diff)
downloadcpython-d5e5a2aa284d610b2bf1fb948c0e8da348ad2733.zip
cpython-d5e5a2aa284d610b2bf1fb948c0e8da348ad2733.tar.gz
cpython-d5e5a2aa284d610b2bf1fb948c0e8da348ad2733.tar.bz2
SF Patch [ 429024 ] deal with some unary ops at compile time
Revised version of Fred's patch, including support for ~ operator. 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. For ~, 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).
Diffstat (limited to 'Python')
-rw-r--r--Python/compile.c69
1 files changed, 66 insertions, 3 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 18f6c71..9a2d50b 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1840,18 +1840,81 @@ com_power(struct compiling *c, node *n)
}
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 void
com_factor(struct compiling *c, node *n)
{
+ int childtype = TYPE(CHILD(n, 0));
REQ(n, factor);
- if (TYPE(CHILD(n, 0)) == PLUS) {
+ /* 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.
+ */
+ if ((childtype == PLUS || childtype == MINUS || childtype == TILDE)
+ && TYPE(CHILD(n, 1)) == factor
+ && TYPE(CHILD(CHILD(n, 1), 0)) == power
+ && TYPE(CHILD(CHILD(CHILD(n, 1), 0), 0)) == atom
+ && TYPE(CHILD(CHILD(CHILD(CHILD(n, 1), 0), 0), 0)) == NUMBER) {
+ node *constant = CHILD(CHILD(CHILD(n, 1), 0), 0);
+ if (childtype == TILDE) {
+ com_invert_constant(c, CHILD(constant, 0));
+ return;
+ }
+ if (childtype == MINUS) {
+ node *numnode = CHILD(constant, 0);
+ char *s = malloc(strlen(STR(numnode)) + 2);
+ if (s == NULL) {
+ com_error(c, PyExc_MemoryError, "");
+ com_addbyte(c, 255);
+ return;
+ }
+ s[0] = '-';
+ strcpy(s + 1, STR(numnode));
+ free(STR(numnode));
+ STR(numnode) = s;
+ }
+ com_atom(c, constant);
+ }
+ else if (childtype == PLUS) {
com_factor(c, CHILD(n, 1));
com_addbyte(c, UNARY_POSITIVE);
}
- else if (TYPE(CHILD(n, 0)) == MINUS) {
+ else if (childtype == MINUS) {
com_factor(c, CHILD(n, 1));
com_addbyte(c, UNARY_NEGATIVE);
}
- else if (TYPE(CHILD(n, 0)) == TILDE) {
+ else if (childtype == TILDE) {
com_factor(c, CHILD(n, 1));
com_addbyte(c, UNARY_INVERT);
}