summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1991-10-24 14:59:31 (GMT)
committerGuido van Rossum <guido@python.org>1991-10-24 14:59:31 (GMT)
commit7928cd7636060c09da613d6f226a54903b86740a (patch)
treea098fc51fb6d3beb0efc3a7905c762190443b183
parent7a6dfa7d79597f29866033ecf648457fe7572a8f (diff)
downloadcpython-7928cd7636060c09da613d6f226a54903b86740a.zip
cpython-7928cd7636060c09da613d6f226a54903b86740a.tar.gz
cpython-7928cd7636060c09da613d6f226a54903b86740a.tar.bz2
Added shift and mask ops.
-rw-r--r--Include/opcode.h8
-rw-r--r--Include/token.h10
-rw-r--r--Objects/intobject.c108
-rw-r--r--Python/ceval.c170
-rw-r--r--Python/compile.c159
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;