Commit f25cab23 authored by Guido van Rossum's avatar Guido van Rossum

Added shift and mask ops.

parent c8dc6467
...@@ -35,6 +35,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -35,6 +35,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define UNARY_NOT 12 #define UNARY_NOT 12
#define UNARY_CONVERT 13 #define UNARY_CONVERT 13
#define UNARY_CALL 14 #define UNARY_CALL 14
#define UNARY_INVERT 15
#define BINARY_MULTIPLY 20 #define BINARY_MULTIPLY 20
#define BINARY_DIVIDE 21 #define BINARY_DIVIDE 21
...@@ -56,6 +57,13 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -56,6 +57,13 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define STORE_SUBSCR 60 #define STORE_SUBSCR 60
#define DELETE_SUBSCR 61 #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_EXPR 70
#define PRINT_ITEM 71 #define PRINT_ITEM 71
#define PRINT_NEWLINE 72 #define PRINT_NEWLINE 72
......
...@@ -56,10 +56,14 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -56,10 +56,14 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define NOTEQUAL 29 #define NOTEQUAL 29
#define LESSEQUAL 30 #define LESSEQUAL 30
#define GREATEREQUAL 31 #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! */ /* Don't forget to update the table tok_name in tokenizer.c! */
#define OP 32 #define OP 36
#define ERRORTOKEN 33 #define ERRORTOKEN 37
#define N_TOKENS 34 #define N_TOKENS 38
/* Special definitions for cooperation with parser */ /* Special definitions for cooperation with parser */
......
...@@ -208,13 +208,30 @@ int_div(v, w) ...@@ -208,13 +208,30 @@ int_div(v, w)
intobject *v; intobject *v;
register object *w; register object *w;
{ {
register long a, b, x;
if (!is_intobject(w)) { if (!is_intobject(w)) {
err_badarg(); err_badarg();
return NULL; return NULL;
} }
if (((intobject *)w) -> ob_ival == 0) if (((intobject *)w) -> ob_ival == 0)
return err_zdiv(); 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 * static object *
...@@ -228,6 +245,7 @@ int_rem(v, w) ...@@ -228,6 +245,7 @@ int_rem(v, w)
} }
if (((intobject *)w) -> ob_ival == 0) if (((intobject *)w) -> ob_ival == 0)
return err_zdiv(); return err_zdiv();
/* XXX Need to fix this similar to int_div */
return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival); return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
} }
...@@ -336,6 +354,88 @@ int_nonzero(v) ...@@ -336,6 +354,88 @@ int_nonzero(v)
return v->ob_ival != 0; 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 = { static number_methods int_as_number = {
int_add, /*nb_add*/ int_add, /*nb_add*/
int_sub, /*nb_subtract*/ int_sub, /*nb_subtract*/
...@@ -348,6 +448,12 @@ static number_methods int_as_number = { ...@@ -348,6 +448,12 @@ static number_methods int_as_number = {
int_pos, /*nb_positive*/ int_pos, /*nb_positive*/
int_abs, /*nb_absolute*/ int_abs, /*nb_absolute*/
int_nonzero, /*nb_nonzero*/ 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 = { typeobject Inttype = {
......
...@@ -51,6 +51,12 @@ static object *rem(); ...@@ -51,6 +51,12 @@ static object *rem();
static object *neg(); static object *neg();
static object *pos(); static object *pos();
static object *not(); 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_builtin();
static object *call_function(); static object *call_function();
static object *apply_subscript(); static object *apply_subscript();
...@@ -273,6 +279,13 @@ eval_code(co, globals, locals, arg) ...@@ -273,6 +279,13 @@ eval_code(co, globals, locals, arg)
DECREF(v); DECREF(v);
PUSH(x); PUSH(x);
break; break;
case UNARY_INVERT:
v = POP();
x = invert(v);
DECREF(v);
PUSH(x);
break;
case BINARY_MULTIPLY: case BINARY_MULTIPLY:
w = POP(); w = POP();
...@@ -340,6 +353,51 @@ eval_code(co, globals, locals, arg) ...@@ -340,6 +353,51 @@ eval_code(co, globals, locals, arg)
PUSH(x); PUSH(x);
break; 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+0:
case SLICE+1: case SLICE+1:
case SLICE+2: case SLICE+2:
...@@ -1001,6 +1059,106 @@ testbool(v) ...@@ -1001,6 +1059,106 @@ testbool(v)
return 1; 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 * static object *
add(v, w) add(v, w)
object *v, *w; object *v, *w;
...@@ -1127,6 +1285,18 @@ pos(v) ...@@ -1127,6 +1285,18 @@ pos(v)
return NULL; 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 * static object *
not(v) not(v)
object *v; object *v;
......
...@@ -689,6 +689,10 @@ com_factor(c, n) ...@@ -689,6 +689,10 @@ com_factor(c, n)
com_factor(c, CHILD(n, 1)); com_factor(c, CHILD(n, 1));
com_addbyte(c, UNARY_NEGATIVE); com_addbyte(c, UNARY_NEGATIVE);
} }
else if (TYPE(CHILD(n, 0)) == TILDE) {
com_factor(c, CHILD(n, 1));
com_addbyte(c, UNARY_INVERT);
}
else { else {
com_atom(c, CHILD(n, 0)); com_atom(c, CHILD(n, 0));
for (i = 1; i < NCH(n); i++) for (i = 1; i < NCH(n); i++)
...@@ -719,7 +723,7 @@ com_term(c, n) ...@@ -719,7 +723,7 @@ com_term(c, n)
break; break;
default: default:
err_setstr(SystemError, err_setstr(SystemError,
"com_term: term operator not *, / or %"); "com_term: operator not *, / or %");
c->c_errors++; c->c_errors++;
op = 255; op = 255;
} }
...@@ -728,13 +732,13 @@ com_term(c, n) ...@@ -728,13 +732,13 @@ com_term(c, n)
} }
static void static void
com_expr(c, n) com_arith_expr(c, n)
struct compiling *c; struct compiling *c;
node *n; node *n;
{ {
int i; int i;
int op; int op;
REQ(n, expr); REQ(n, arith_expr);
com_term(c, CHILD(n, 0)); com_term(c, CHILD(n, 0));
for (i = 2; i < NCH(n); i += 2) { for (i = 2; i < NCH(n); i += 2) {
com_term(c, CHILD(n, i)); com_term(c, CHILD(n, i));
...@@ -747,7 +751,107 @@ com_expr(c, n) ...@@ -747,7 +751,107 @@ com_expr(c, n)
break; break;
default: default:
err_setstr(SystemError, 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++; c->c_errors++;
op = 255; op = 255;
} }
...@@ -1065,35 +1169,12 @@ com_assign(c, n, assigning) ...@@ -1065,35 +1169,12 @@ com_assign(c, n, assigning)
case test: case test:
case and_test: case and_test:
case not_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: 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: case expr:
if (NCH(n) > 1) { case xor_expr:
err_setstr(TypeError, case and_expr:
"can't assign to operator"); case shift_expr:
c->c_errors++; case arith_expr:
return;
}
n = CHILD(n, 0);
break;
case term: case term:
if (NCH(n) > 1) { if (NCH(n) > 1) {
err_setstr(TypeError, err_setstr(TypeError,
...@@ -1104,8 +1185,8 @@ com_assign(c, n, assigning) ...@@ -1104,8 +1185,8 @@ com_assign(c, n, assigning)
n = CHILD(n, 0); n = CHILD(n, 0);
break; break;
case factor: /* ('+'|'-') factor | atom trailer* */ case factor: /* ('+'|'-'|'~') factor | atom trailer* */
if (TYPE(CHILD(n, 0)) != atom) { /* '+' | '-' */ if (TYPE(CHILD(n, 0)) != atom) { /* '+'|'-'|'~' */
err_setstr(TypeError, err_setstr(TypeError,
"can't assign to operator"); "can't assign to operator");
c->c_errors++; c->c_errors++;
...@@ -1728,6 +1809,18 @@ com_node(c, n) ...@@ -1728,6 +1809,18 @@ com_node(c, n)
case expr: case expr:
com_expr(c, n); com_expr(c, n);
break; 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: case term:
com_term(c, n); com_term(c, n);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment