diff options
author | Guido van Rossum <guido@python.org> | 1991-10-24 14:59:31 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1991-10-24 14:59:31 (GMT) |
commit | 7928cd7636060c09da613d6f226a54903b86740a (patch) | |
tree | a098fc51fb6d3beb0efc3a7905c762190443b183 | |
parent | 7a6dfa7d79597f29866033ecf648457fe7572a8f (diff) | |
download | cpython-7928cd7636060c09da613d6f226a54903b86740a.zip cpython-7928cd7636060c09da613d6f226a54903b86740a.tar.gz cpython-7928cd7636060c09da613d6f226a54903b86740a.tar.bz2 |
Added shift and mask ops.
-rw-r--r-- | Include/opcode.h | 8 | ||||
-rw-r--r-- | Include/token.h | 10 | ||||
-rw-r--r-- | Objects/intobject.c | 108 | ||||
-rw-r--r-- | Python/ceval.c | 170 | ||||
-rw-r--r-- | Python/compile.c | 159 |
5 files changed, 418 insertions, 37 deletions
diff --git a/Include/opcode.h b/Include/opcode.h index 7edf661..62cedb3 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -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 diff --git a/Include/token.h b/Include/token.h index 9c1ed71..d29c784 100644 --- a/Include/token.h +++ b/Include/token.h @@ -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 */ diff --git a/Objects/intobject.c b/Objects/intobject.c index 91c43b9..c8b2fac 100644 --- a/Objects/intobject.c +++ b/Objects/intobject.c @@ -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 = { diff --git a/Python/ceval.c b/Python/ceval.c index 76869ff..7399623 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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: @@ -1002,6 +1060,106 @@ testbool(v) } 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; { @@ -1128,6 +1286,18 @@ pos(v) } 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; { diff --git a/Python/compile.c b/Python/compile.c index 5939196..09d461a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -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; |