]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Added shift and mask ops.
authorGuido van Rossum <guido@python.org>
Thu, 24 Oct 1991 14:59:31 +0000 (14:59 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 24 Oct 1991 14:59:31 +0000 (14:59 +0000)
Include/opcode.h
Include/token.h
Objects/intobject.c
Python/ceval.c
Python/compile.c

index 7edf6616f6161605909375eb7d1ec1f94abaa152..62cedb3a211c72a5cb1355ab57abf7eccd949003 100644 (file)
@@ -35,6 +35,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define UNARY_NOT      12
 #define UNARY_CONVERT  13
 #define UNARY_CALL     14
+#define UNARY_INVERT   15
 
 #define BINARY_MULTIPLY        20
 #define BINARY_DIVIDE  21
@@ -56,6 +57,13 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define STORE_SUBSCR   60
 #define DELETE_SUBSCR  61
 
+#define BINARY_LSHIFT  62
+#define BINARY_RSHIFT  63
+#define BINARY_AND     64
+#define BINARY_XOR     65
+#define BINARY_OR      66
+
+
 #define PRINT_EXPR     70
 #define PRINT_ITEM     71
 #define PRINT_NEWLINE  72
index 9c1ed716a3d18203f5f158369623a3fbb046e941..d29c7843f81a7c45b4eeab80089ee1f30b134346 100644 (file)
@@ -56,10 +56,14 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define NOTEQUAL       29
 #define LESSEQUAL      30
 #define GREATEREQUAL   31
+#define TILDE          32
+#define CIRCUMFLEX     33
+#define LEFTSHIFT      34
+#define RIGHTSHIFT     35
 /* Don't forget to update the table tok_name in tokenizer.c! */
-#define OP             32
-#define ERRORTOKEN     33
-#define N_TOKENS       34
+#define OP             36
+#define ERRORTOKEN     37
+#define N_TOKENS       38
 
 /* Special definitions for cooperation with parser */
 
index 91c43b97b809c63df844bdcbbbbcaa77c8fe47e1..c8b2fac4e376e518b1897ffc64796d445e10d174 100644 (file)
@@ -208,13 +208,30 @@ int_div(v, w)
        intobject *v;
        register object *w;
 {
+       register long a, b, x;
        if (!is_intobject(w)) {
                err_badarg();
                return NULL;
        }
        if (((intobject *)w) -> ob_ival == 0)
                return err_zdiv();
-       return newintobject(v->ob_ival / ((intobject *)w) -> ob_ival);
+       a = v->ob_ival;
+       b = ((intobject *)w) -> ob_ival;
+       /* Make sure we always truncate towards zero */
+       /* XXX What if a == -0x80000000? */
+       if (a < 0) {
+               if (b < 0)
+                       x = -a / -b;
+               else
+                       x = -(-a / b);
+       }
+       else {
+               if (b < 0)
+                       x = -(a / -b);
+               else
+                       x = a / b;
+       }
+       return newintobject(x);
 }
 
 static object *
@@ -228,6 +245,7 @@ int_rem(v, w)
        }
        if (((intobject *)w) -> ob_ival == 0)
                return err_zdiv();
+       /* XXX Need to fix this similar to int_div */
        return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
 }
 
@@ -336,6 +354,88 @@ int_nonzero(v)
        return v->ob_ival != 0;
 }
 
+static object *
+int_invert(v)
+       intobject *v;
+{
+       return newintobject(~v->ob_ival);
+}
+
+static object *
+int_lshift(v, w)
+       intobject *v;
+       register object *w;
+{
+       register long a, b;
+       if (!is_intobject(w)) {
+               err_badarg();
+               return NULL;
+       }
+       a = v->ob_ival;
+       b = ((intobject *)w) -> ob_ival;
+       return newintobject((unsigned long)a << b);
+}
+
+static object *
+int_rshift(v, w)
+       intobject *v;
+       register object *w;
+{
+       register long a, b;
+       if (!is_intobject(w)) {
+               err_badarg();
+               return NULL;
+       }
+       a = v->ob_ival;
+       b = ((intobject *)w) -> ob_ival;
+       return newintobject((unsigned long)a >> b);
+}
+
+static object *
+int_and(v, w)
+       intobject *v;
+       register object *w;
+{
+       register long a, b;
+       if (!is_intobject(w)) {
+               err_badarg();
+               return NULL;
+       }
+       a = v->ob_ival;
+       b = ((intobject *)w) -> ob_ival;
+       return newintobject(a & b);
+}
+
+static object *
+int_xor(v, w)
+       intobject *v;
+       register object *w;
+{
+       register long a, b;
+       if (!is_intobject(w)) {
+               err_badarg();
+               return NULL;
+       }
+       a = v->ob_ival;
+       b = ((intobject *)w) -> ob_ival;
+       return newintobject(a ^ b);
+}
+
+static object *
+int_or(v, w)
+       intobject *v;
+       register object *w;
+{
+       register long a, b;
+       if (!is_intobject(w)) {
+               err_badarg();
+               return NULL;
+       }
+       a = v->ob_ival;
+       b = ((intobject *)w) -> ob_ival;
+       return newintobject(a | b);
+}
+
 static number_methods int_as_number = {
        int_add,        /*nb_add*/
        int_sub,        /*nb_subtract*/
@@ -348,6 +448,12 @@ static number_methods int_as_number = {
        int_pos,        /*nb_positive*/
        int_abs,        /*nb_absolute*/
        int_nonzero,    /*nb_nonzero*/
+       int_invert,     /*nb_invert*/
+       int_lshift,     /*nb_lshift*/
+       int_rshift,     /*nb_rshift*/
+       int_and,        /*nb_and*/
+       int_xor,        /*nb_xor*/
+       int_or,         /*nb_or*/
 };
 
 typeobject Inttype = {
index 76869ff7d9fbd5d34279ca26dc220faaaf125c3b..7399623735a64374a1d779ee972b4c0d4c3cf059 100644 (file)
@@ -51,6 +51,12 @@ static object *rem();
 static object *neg();
 static object *pos();
 static object *not();
+static object *invert();
+static object *lshift();
+static object *rshift();
+static object *and();
+static object *xor();
+static object *or();
 static object *call_builtin();
 static object *call_function();
 static object *apply_subscript();
@@ -273,6 +279,13 @@ eval_code(co, globals, locals, arg)
                        DECREF(v);
                        PUSH(x);
                        break;
+                       
+               case UNARY_INVERT:
+                       v = POP();
+                       x = invert(v);
+                       DECREF(v);
+                       PUSH(x);
+                       break;
                
                case BINARY_MULTIPLY:
                        w = POP();
@@ -340,6 +353,51 @@ eval_code(co, globals, locals, arg)
                        PUSH(x);
                        break;
                
+               case BINARY_LSHIFT:
+                       w = POP();
+                       v = POP();
+                       x = lshift(v, w);
+                       DECREF(v);
+                       DECREF(w);
+                       PUSH(x);
+                       break;
+               
+               case BINARY_RSHIFT:
+                       w = POP();
+                       v = POP();
+                       x = rshift(v, w);
+                       DECREF(v);
+                       DECREF(w);
+                       PUSH(x);
+                       break;
+               
+               case BINARY_AND:
+                       w = POP();
+                       v = POP();
+                       x = and(v, w);
+                       DECREF(v);
+                       DECREF(w);
+                       PUSH(x);
+                       break;
+               
+               case BINARY_XOR:
+                       w = POP();
+                       v = POP();
+                       x = xor(v, w);
+                       DECREF(v);
+                       DECREF(w);
+                       PUSH(x);
+                       break;
+               
+               case BINARY_OR:
+                       w = POP();
+                       v = POP();
+                       x = or(v, w);
+                       DECREF(v);
+                       DECREF(w);
+                       PUSH(x);
+                       break;
+               
                case SLICE+0:
                case SLICE+1:
                case SLICE+2:
@@ -1001,6 +1059,106 @@ testbool(v)
        return 1;
 }
 
+static object *
+or(v, w)
+       object *v, *w;
+{
+       if (v->ob_type->tp_as_number != NULL) {
+               object *x;
+               object * (*f) FPROTO((object *, object *));
+               if (coerce(&v, &w) != 0)
+                       return NULL;
+               if ((f = v->ob_type->tp_as_number->nb_or) != NULL)
+                       x = (*f)(v, w);
+               DECREF(v);
+               DECREF(w);
+               if (f != NULL)
+                       return x;
+       }
+       err_setstr(TypeError, "bad operand type(s) for |");
+       return NULL;
+}
+
+static object *
+xor(v, w)
+       object *v, *w;
+{
+       if (v->ob_type->tp_as_number != NULL) {
+               object *x;
+               object * (*f) FPROTO((object *, object *));
+               if (coerce(&v, &w) != 0)
+                       return NULL;
+               if ((f = v->ob_type->tp_as_number->nb_xor) != NULL)
+                       x = (*f)(v, w);
+               DECREF(v);
+               DECREF(w);
+               if (f != NULL)
+                       return x;
+       }
+       err_setstr(TypeError, "bad operand type(s) for ^");
+       return NULL;
+}
+
+static object *
+and(v, w)
+       object *v, *w;
+{
+       if (v->ob_type->tp_as_number != NULL) {
+               object *x;
+               object * (*f) FPROTO((object *, object *));
+               if (coerce(&v, &w) != 0)
+                       return NULL;
+               if ((f = v->ob_type->tp_as_number->nb_and) != NULL)
+                       x = (*f)(v, w);
+               DECREF(v);
+               DECREF(w);
+               if (f != NULL)
+                       return x;
+       }
+       err_setstr(TypeError, "bad operand type(s) for &");
+       return NULL;
+}
+
+static object *
+lshift(v, w)
+       object *v, *w;
+{
+       if (v->ob_type->tp_as_number != NULL) {
+               object *x;
+               object * (*f) FPROTO((object *, object *));
+               if (coerce(&v, &w) != 0)
+                       return NULL;
+               if ((f = v->ob_type->tp_as_number->nb_lshift) != NULL)
+                       x = (*f)(v, w);
+               DECREF(v);
+               DECREF(w);
+               if (f != NULL)
+                       return x;
+       }
+       err_setstr(TypeError, "bad operand type(s) for <<");
+       return NULL;
+}
+
+static object *
+rshift(v, w)
+       object *v, *w;
+{
+       if (v->ob_type->tp_as_number != NULL) {
+               object *x;
+               object * (*f) FPROTO((object *, object *));
+               if (coerce(&v, &w) != 0)
+                       return NULL;
+               if ((f = v->ob_type->tp_as_number->nb_rshift) != NULL)
+                       x = (*f)(v, w);
+               DECREF(v);
+               DECREF(w);
+               if (f != NULL)
+                       return x;
+       }
+       err_setstr(TypeError, "bad operand type(s) for >>");
+       return NULL;
+}
+
 static object *
 add(v, w)
        object *v, *w;
@@ -1127,6 +1285,18 @@ pos(v)
        return NULL;
 }
 
+static object *
+invert(v)
+       object *v;
+{
+       object * (*f) FPROTO((object *, object *));
+       if (v->ob_type->tp_as_number != NULL &&
+               (f = v->ob_type->tp_as_number->nb_invert) != NULL)
+               return (*f)(v);
+       err_setstr(TypeError, "bad operand type(s) for unary ~");
+       return NULL;
+}
+
 static object *
 not(v)
        object *v;
index 59391968e6bda7b3a42dc13e7661e8b9e3ff8a31..09d461a49ab5f65eb5c18654289d6129db62399d 100644 (file)
@@ -689,6 +689,10 @@ com_factor(c, n)
                com_factor(c, CHILD(n, 1));
                com_addbyte(c, UNARY_NEGATIVE);
        }
+       else if (TYPE(CHILD(n, 0)) == TILDE) {
+               com_factor(c, CHILD(n, 1));
+               com_addbyte(c, UNARY_INVERT);
+       }
        else {
                com_atom(c, CHILD(n, 0));
                for (i = 1; i < NCH(n); i++)
@@ -719,7 +723,7 @@ com_term(c, n)
                        break;
                default:
                        err_setstr(SystemError,
-                               "com_term: term operator not *, / or %");
+                               "com_term: operator not *, / or %");
                        c->c_errors++;
                        op = 255;
                }
@@ -728,13 +732,13 @@ com_term(c, n)
 }
 
 static void
-com_expr(c, n)
+com_arith_expr(c, n)
        struct compiling *c;
        node *n;
 {
        int i;
        int op;
-       REQ(n, expr);
+       REQ(n, arith_expr);
        com_term(c, CHILD(n, 0));
        for (i = 2; i < NCH(n); i += 2) {
                com_term(c, CHILD(n, i));
@@ -747,7 +751,107 @@ com_expr(c, n)
                        break;
                default:
                        err_setstr(SystemError,
-                               "com_expr: expr operator not + or -");
+                               "com_arith_expr: operator not + or -");
+                       c->c_errors++;
+                       op = 255;
+               }
+               com_addbyte(c, op);
+       }
+}
+
+static void
+com_shift_expr(c, n)
+       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:
+                       err_setstr(SystemError,
+                               "com_shift_expr: operator not << or >>");
+                       c->c_errors++;
+                       op = 255;
+               }
+               com_addbyte(c, op);
+       }
+}
+
+static void
+com_and_expr(c, n)
+       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 {
+                       err_setstr(SystemError,
+                               "com_and_expr: operator not &");
+                       c->c_errors++;
+                       op = 255;
+               }
+               com_addbyte(c, op);
+       }
+}
+
+static void
+com_xor_expr(c, n)
+       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));
+               if (TYPE(CHILD(n, i-1)) == CIRCUMFLEX) {
+                       op = BINARY_XOR;
+               }
+               else {
+                       err_setstr(SystemError,
+                               "com_xor_expr: operator not ^");
+                       c->c_errors++;
+                       op = 255;
+               }
+               com_addbyte(c, op);
+       }
+}
+
+static void
+com_expr(c, n)
+       struct compiling *c;
+       node *n;
+{
+       int i;
+       int op;
+       REQ(n, expr);
+       com_xor_expr(c, CHILD(n, 0));
+       for (i = 2; i < NCH(n); i += 2) {
+               com_xor_expr(c, CHILD(n, i));
+               if (TYPE(CHILD(n, i-1)) == VBAR) {
+                       op = BINARY_OR;
+               }
+               else {
+                       err_setstr(SystemError,
+                               "com_expr: expr operator not |");
                        c->c_errors++;
                        op = 255;
                }
@@ -1065,35 +1169,12 @@ com_assign(c, n, assigning)
                case test:
                case and_test:
                case not_test:
-                       if (NCH(n) > 1) {
-                               err_setstr(TypeError,
-                                       "can't assign to operator");
-                               c->c_errors++;
-                               return;
-                       }
-                       n = CHILD(n, 0);
-                       break;
-               
                case comparison:
-                       if (NCH(n) > 1) {
-                               err_setstr(TypeError,
-                                       "can't assign to operator");
-                               c->c_errors++;
-                               return;
-                       }
-                       n = CHILD(n, 0);
-                       break;
-               
                case expr:
-                       if (NCH(n) > 1) {
-                               err_setstr(TypeError,
-                                       "can't assign to operator");
-                               c->c_errors++;
-                               return;
-                       }
-                       n = CHILD(n, 0);
-                       break;
-               
+               case xor_expr:
+               case and_expr:
+               case shift_expr:
+               case arith_expr:
                case term:
                        if (NCH(n) > 1) {
                                err_setstr(TypeError,
@@ -1104,8 +1185,8 @@ com_assign(c, n, assigning)
                        n = CHILD(n, 0);
                        break;
                
-               case factor: /* ('+'|'-') factor | atom trailer* */
-                       if (TYPE(CHILD(n, 0)) != atom) { /* '+' | '-' */
+               case factor: /* ('+'|'-'|'~') factor | atom trailer* */
+                       if (TYPE(CHILD(n, 0)) != atom) { /* '+'|'-'|'~' */
                                err_setstr(TypeError,
                                        "can't assign to operator");
                                c->c_errors++;
@@ -1728,6 +1809,18 @@ com_node(c, n)
        case expr:
                com_expr(c, n);
                break;
+       case xor_expr:
+               com_xor_expr(c, n);
+               break;
+       case and_expr:
+               com_and_expr(c, n);
+               break;
+       case shift_expr:
+               com_shift_expr(c, n);
+               break;
+       case arith_expr:
+               com_arith_expr(c, n);
+               break;
        case term:
                com_term(c, n);
                break;