Added shift and mask ops.
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 @@
 #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 @@
 #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 @@
 #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 @@
 	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 @@
 	}
 	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 @@
 	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 @@
 	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 *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 @@
 			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 @@
 			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 @@
 }
 
 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 @@
 }
 
 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, 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,111 @@
 			break;
 		default:
 			err_setstr(SystemError,
-				"com_term: term operator not *, / or %");
+				"com_term: operator not *, / or %");
+			c->c_errors++;
+			op = 255;
+		}
+		com_addbyte(c, op);
+	}
+}
+
+static void
+com_arith_expr(c, n)
+	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:
+			err_setstr(SystemError,
+				"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;
 		}
@@ -735,19 +843,15 @@
 	int i;
 	int op;
 	REQ(n, expr);
-	com_term(c, CHILD(n, 0));
+	com_xor_expr(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_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 + or -");
+				"com_expr: expr operator not |");
 			c->c_errors++;
 			op = 255;
 		}
@@ -1065,35 +1169,12 @@
 		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 @@
 			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 @@
 	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;