diff -crN --exclude=CVS src/Grammar/Grammar src-augassign/Grammar/Grammar *** src/Grammar/Grammar Tue Aug 22 17:39:43 2000 --- src-augassign/Grammar/Grammar Tue Aug 22 14:07:38 2000 *************** *** 30,38 **** stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE #small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt ! small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt ! expr_stmt: testlist ('=' testlist)* ! # For assignments, additional restrictions enforced by the interpreter print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] ) del_stmt: 'del' exprlist pass_stmt: 'pass' --- 30,39 ---- stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE #small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt ! small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt ! expr_stmt: testlist (augassign testlist | ('=' testlist)*) ! augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' ! # For normal assignments, additional restrictions enforced by the interpreter print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] ) del_stmt: 'del' exprlist pass_stmt: 'pass' diff -crN --exclude=CVS src/Include/abstract.h src-augassign/Include/abstract.h *** src/Include/abstract.h Thu Aug 3 18:42:14 2000 --- src-augassign/Include/abstract.h Mon Aug 21 17:39:27 2000 *************** *** 664,669 **** --- 664,771 ---- float(o). */ + /* In-place variants of (some of) the above number protocol functions */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceAdd(PyObject *o1, PyObject *o2); + + /* + Returns the result of adding o2 to o1, possibly in-place, or null + on failure. This is the equivalent of the Python expression: + o1 += o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceSubtract(PyObject *o1, PyObject *o2); + + /* + Returns the result of subtracting o2 from o1, possibly in-place or + null on failure. This is the equivalent of the Python expression: + o1 -= o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceMultiply(PyObject *o1, PyObject *o2); + + /* + Returns the result of multiplying o1 by o2, possibly in-place, or + null on failure. This is the equivalent of the Python expression: + o1 *= o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceDivide(PyObject *o1, PyObject *o2); + + /* + Returns the result of dividing o1 by o2, possibly in-place, or null + on failure. This is the equivalent of the Python expression: + o1 /= o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceRemainder(PyObject *o1, PyObject *o2); + + /* + Returns the remainder of dividing o1 by o2, possibly in-place, or + null on failure. This is the equivalent of the Python expression: + o1 %= o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlacePower(PyObject *o1, PyObject *o2, + PyObject *o3); + + /* + Returns the result of raising o1 to the power of o2, possibly + in-place, or null on failure. This is the equivalent of the Python + expression: o1 **= o2, or pow(o1, o2, o3) if o3 is present. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceLshift(PyObject *o1, PyObject *o2); + + /* + Returns the result of left shifting o1 by o2, possibly in-place, or + null on failure. This is the equivalent of the Python expression: + o1 <<= o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceRshift(PyObject *o1, PyObject *o2); + + /* + Returns the result of right shifting o1 by o2, possibly in-place or + null on failure. This is the equivalent of the Python expression: + o1 >>= o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceAnd(PyObject *o1, PyObject *o2); + + /* + Returns the result of bitwise and of o1 and o2, possibly in-place, + or null on failure. This is the equivalent of the Python + expression: o1 &= o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceXor(PyObject *o1, PyObject *o2); + + /* + Returns the bitwise exclusive or of o1 by o2, possibly in-place, or + null on failure. This is the equivalent of the Python expression: + o1 ^= o2. + + */ + + DL_IMPORT(PyObject *) PyNumber_InPlaceOr(PyObject *o1, PyObject *o2); + + /* + Returns the result of bitwise or or o1 and o2, possibly in-place, + or null on failure. This is the equivalent of the Python + expression: o1 |= o2. + + */ + /* Sequence protocol:*/ *************** *** 822,827 **** --- 924,949 ---- Return the first index for which o[i]=value. On error, return -1. This is equivalent to the Python expression: o.index(value). + */ + + /* In-place versions of some of the above Sequence functions. */ + + DL_IMPORT(PyObject *) PySequence_InPlaceConcat(PyObject *o1, PyObject *o2); + + /* + Append o2 to o1, in-place when possible. Return the resulting + object, which could be o1, or NULL on failure. This is the + equivalent of the Python expression: o1 += o2. + + */ + + DL_IMPORT(PyObject *) PySequence_InPlaceRepeat(PyObject *o, int count); + + /* + Repeat o1 by count, in-place when possible. Return the resulting + object, which could be o1, or NULL on failure. This is the + equivalent of the Python expression: o1 *= count. + */ /* Mapping protocol:*/ diff -crN --exclude=CVS src/Include/classobject.h src-augassign/Include/classobject.h *** src/Include/classobject.h Sun Jul 9 02:20:36 2000 --- src-augassign/Include/classobject.h Mon Aug 21 14:22:43 2000 *************** *** 73,78 **** --- 73,82 ---- PyObject * (*)(PyObject *, PyObject *)); + extern DL_IMPORT(PyObject *) + PyInstance_DoInPlaceOp(PyObject *, PyObject *, char *, char *, char *, + PyObject * (*)(PyObject *, PyObject *)); + #ifdef __cplusplus } #endif diff -crN --exclude=CVS src/Include/object.h src-augassign/Include/object.h *** src/Include/object.h Sun Jul 16 14:04:30 2000 --- src-augassign/Include/object.h Mon Aug 21 17:35:07 2000 *************** *** 151,156 **** --- 151,167 ---- unaryfunc nb_float; unaryfunc nb_oct; unaryfunc nb_hex; + binaryfunc nb_inplace_add; + binaryfunc nb_inplace_subtract; + binaryfunc nb_inplace_multiply; + binaryfunc nb_inplace_divide; + binaryfunc nb_inplace_remainder; + ternaryfunc nb_inplace_power; + binaryfunc nb_inplace_lshift; + binaryfunc nb_inplace_rshift; + binaryfunc nb_inplace_and; + binaryfunc nb_inplace_xor; + binaryfunc nb_inplace_or; } PyNumberMethods; typedef struct { *************** *** 162,167 **** --- 173,180 ---- intobjargproc sq_ass_item; intintobjargproc sq_ass_slice; objobjproc sq_contains; + binaryfunc sq_inplace_concat; + intargfunc sq_inplace_repeat; } PySequenceMethods; typedef struct { *************** *** 315,322 **** #define Py_TPFLAGS_GC 0 #endif #define Py_TPFLAGS_DEFAULT (Py_TPFLAGS_HAVE_GETCHARBUFFER | \ ! Py_TPFLAGS_HAVE_SEQUENCE_IN) #define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0) --- 328,339 ---- #define Py_TPFLAGS_GC 0 #endif + /* PySequenceMethods and PyNumberMethods contain in-place operators */ + #define Py_TPFLAGS_HAVE_INPLACEOPS (1L<<3) + #define Py_TPFLAGS_DEFAULT (Py_TPFLAGS_HAVE_GETCHARBUFFER | \ ! Py_TPFLAGS_HAVE_SEQUENCE_IN | \ ! Py_TPFLAGS_HAVE_INPLACEOPS) #define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0) diff -crN --exclude=CVS src/Include/opcode.h src-augassign/Include/opcode.h *** src/Include/opcode.h Tue Aug 22 17:39:43 2000 --- src-augassign/Include/opcode.h Tue Aug 22 14:53:40 2000 *************** *** 21,26 **** --- 21,27 ---- #define ROT_TWO 2 #define ROT_THREE 3 #define DUP_TOP 4 + #define ROT_FOUR 5 #define UNARY_POSITIVE 10 #define UNARY_NEGATIVE 11 *************** *** 47,52 **** --- 48,58 ---- #define DELETE_SLICE 50 /* Also uses 51-53 */ + #define INPLACE_ADD 55 + #define INPLACE_SUBTRACT 56 + #define INPLACE_MULTIPLY 57 + #define INPLACE_DIVIDE 58 + #define INPLACE_MODULO 59 #define STORE_SUBSCR 60 #define DELETE_SUBSCR 61 *************** *** 55,68 **** #define BINARY_AND 64 #define BINARY_XOR 65 #define BINARY_OR 66 ! #define PRINT_EXPR 70 #define PRINT_ITEM 71 #define PRINT_NEWLINE 72 #define PRINT_ITEM_TO 73 #define PRINT_NEWLINE_TO 74 ! #define BREAK_LOOP 80 #define LOAD_LOCALS 82 --- 61,78 ---- #define BINARY_AND 64 #define BINARY_XOR 65 #define BINARY_OR 66 ! #define INPLACE_POWER 67 #define PRINT_EXPR 70 #define PRINT_ITEM 71 #define PRINT_NEWLINE 72 #define PRINT_ITEM_TO 73 #define PRINT_NEWLINE_TO 74 ! #define INPLACE_LSHIFT 75 ! #define INPLACE_RSHIFT 76 ! #define INPLACE_AND 77 ! #define INPLACE_XOR 78 ! #define INPLACE_OR 79 #define BREAK_LOOP 80 #define LOAD_LOCALS 82 *************** *** 84,90 **** #define DELETE_ATTR 96 /* "" */ #define STORE_GLOBAL 97 /* "" */ #define DELETE_GLOBAL 98 /* "" */ ! #define LOAD_CONST 100 /* Index in const list */ #define LOAD_NAME 101 /* Index in name list */ #define BUILD_TUPLE 102 /* Number of tuple items */ --- 94,100 ---- #define DELETE_ATTR 96 /* "" */ #define STORE_GLOBAL 97 /* "" */ #define DELETE_GLOBAL 98 /* "" */ ! #define DUP_TOPX 99 /* number of items to duplicate */ #define LOAD_CONST 100 /* Index in const list */ #define LOAD_NAME 101 /* Index in name list */ #define BUILD_TUPLE 102 /* Number of tuple items */ diff -crN --exclude=CVS src/Include/token.h src-augassign/Include/token.h *** src/Include/token.h Sun Jul 9 02:55:06 2000 --- src-augassign/Include/token.h Mon Aug 21 14:22:43 2000 *************** *** 53,62 **** #define LEFTSHIFT 34 #define RIGHTSHIFT 35 #define DOUBLESTAR 36 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */ ! #define OP 37 ! #define ERRORTOKEN 38 ! #define N_TOKENS 39 /* Special definitions for cooperation with parser */ --- 53,73 ---- #define LEFTSHIFT 34 #define RIGHTSHIFT 35 #define DOUBLESTAR 36 + #define PLUSEQUAL 37 + #define MINEQUAL 38 + #define STAREQUAL 39 + #define SLASHEQUAL 40 + #define PERCENTEQUAL 41 + #define AMPEREQUAL 42 + #define VBAREQUAL 43 + #define CIRCUMFLEXEQUAL 44 + #define LEFTSHIFTEQUAL 45 + #define RIGHTSHIFTEQUAL 46 + #define DOUBLESTAREQUAL 47 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */ ! #define OP 48 ! #define ERRORTOKEN 49 ! #define N_TOKENS 50 /* Special definitions for cooperation with parser */ diff -crN --exclude=CVS src/Lib/UserList.py src-augassign/Lib/UserList.py *** src/Lib/UserList.py Sun Jul 16 14:04:30 2000 --- src-augassign/Lib/UserList.py Mon Aug 21 17:57:14 2000 *************** *** 51,67 **** return self.__class__(other + self.data) else: return self.__class__(list(other) + self.data) def __mul__(self, n): return self.__class__(self.data*n) __rmul__ = __mul__ def append(self, item): self.data.append(item) def insert(self, i, item): self.data.insert(i, item) ! def pop(self, i=-1): return self.data.pop(i) def remove(self, item): self.data.remove(item) def count(self, item): return self.data.count(item) def index(self, item): return self.data.index(item) def reverse(self): self.data.reverse() ! def sort(self, *args): apply(self.data.sort, args) def extend(self, other): if isinstance(other, UserList): self.data.extend(other.data) --- 51,78 ---- return self.__class__(other + self.data) else: return self.__class__(list(other) + self.data) + def __iadd__(self, other): + if isinstance(other, UserList): + self.data += other.data + elif isinstance(other, self.data): + self.data += other + else: + self.data += list(other) + return self def __mul__(self, n): return self.__class__(self.data*n) __rmul__ = __mul__ + def __imul__(self, n): + self.data *= n + return self def append(self, item): self.data.append(item) def insert(self, i, item): self.data.insert(i, item) ! def pop(self, *args): return self.data.pop(*args) def remove(self, item): self.data.remove(item) def count(self, item): return self.data.count(item) def index(self, item): return self.data.index(item) def reverse(self): self.data.reverse() ! def sort(self, *args): self.data.sort(*args) def extend(self, other): if isinstance(other, UserList): self.data.extend(other.data) diff -crN --exclude=CVS src/Lib/dis.py src-augassign/Lib/dis.py *** src/Lib/dis.py Tue Aug 22 17:39:44 2000 --- src-augassign/Lib/dis.py Tue Aug 22 14:07:41 2000 *************** *** 178,183 **** --- 178,188 ---- def_op('DELETE_SLICE+2', 52) def_op('DELETE_SLICE+3', 53) + def_op('INPLACE_ADD', 55) + def_op('INPLACE_SUBTRACT', 56) + def_op('INPLACE_MULTIPLY', 57) + def_op('INPLACE_DIVIDE', 58) + def_op('INPLACE_MODULO', 59) def_op('STORE_SUBSCR', 60) def_op('DELETE_SUBSCR', 61) *************** *** 193,198 **** --- 198,209 ---- def_op('PRINT_ITEM_TO', 73) def_op('PRINT_NEWLINE_TO', 74) + def_op('INPLACE_POWER', 74) + def_op('INPLACE_LSHIFT', 75) + def_op('INPLACE_RSHIFT', 76) + def_op('INPLACE_AND', 77) + def_op('INPLACE_XOR', 78) + def_op('INPLACE_OR', 79) def_op('BREAK_LOOP', 80) def_op('LOAD_LOCALS', 82) diff -crN --exclude=CVS src/Lib/test/output/test_augassign src-augassign/Lib/test/output/test_augassign *** src/Lib/test/output/test_augassign Thu Jan 1 01:00:00 1970 --- src-augassign/Lib/test/output/test_augassign Mon Aug 21 16:12:50 2000 *************** *** 0 **** --- 1,48 ---- + test_augassign + 6 + [6] + 6 + [1, 2, 3, 4, 1, 2, 3, 4] + [1, 2, 1, 2, 3] + 1 + 1 + 1 + 11 + 1 + 12 + 1 + 1 + 13 + __add__ called + __radd__ called + __iadd__ called + __sub__ called + __rsub__ called + __isub__ called + __mul__ called + __rmul__ called + __imul__ called + __div__ called + __rdiv__ called + __idiv__ called + __mod__ called + __rmod__ called + __imod__ called + __pow__ called + __rpow__ called + __ipow__ called + __or__ called + __ror__ called + __ior__ called + __and__ called + __rand__ called + __iand__ called + __xor__ called + __rxor__ called + __ixor__ called + __rshift__ called + __rrshift__ called + __irshift__ called + __lshift__ called + __rlshift__ called + __ilshift__ called diff -crN --exclude=CVS src/Lib/test/test_augassign.py src-augassign/Lib/test/test_augassign.py *** src/Lib/test/test_augassign.py Thu Jan 1 01:00:00 1970 --- src-augassign/Lib/test/test_augassign.py Mon Aug 21 15:52:55 2000 *************** *** 0 **** --- 1,232 ---- + + # Augmented assignment test. + + x = 2 + x += 1 + x *= 2 + x **= 2 + x -= 8 + x /= 2 + x %= 12 + x &= 2 + x |= 5 + x ^= 1 + + print x + + x = [2] + x[0] += 1 + x[0] *= 2 + x[0] **= 2 + x[0] -= 8 + x[0] /= 2 + x[0] %= 12 + x[0] &= 2 + x[0] |= 5 + x[0] ^= 1 + + print x + + x = {0: 2} + x[0] += 1 + x[0] *= 2 + x[0] **= 2 + x[0] -= 8 + x[0] /= 2 + x[0] %= 12 + x[0] &= 2 + x[0] |= 5 + x[0] ^= 1 + + print x[0] + + x = [1,2] + x += [3,4] + x *= 2 + + print x + + x = [1, 2, 3] + y = x + x[1:2] *= 2 + y[1:2] += [1] + + print x + print x is y + + class aug_test: + def __init__(self, value): + self.val = value + def __radd__(self, val): + return self.val + val + def __add__(self, val): + return aug_test(self.val + val) + + + class aug_test2(aug_test): + def __iadd__(self, val): + self.val = self.val + val + return self + + class aug_test3(aug_test): + def __iadd__(self, val): + return aug_test3(self.val + val) + + x = aug_test(1) + y = x + x += 10 + + print isinstance(x, aug_test) + print y is not x + print x.val + + x = aug_test2(2) + y = x + x += 10 + + print y is x + print x.val + + x = aug_test3(3) + y = x + x += 10 + + print isinstance(x, aug_test3) + print y is not x + print x.val + + class testall: + + def __add__(self, val): + print "__add__ called" + def __radd__(self, val): + print "__radd__ called" + def __iadd__(self, val): + print "__iadd__ called" + return self + + def __sub__(self, val): + print "__sub__ called" + def __rsub__(self, val): + print "__rsub__ called" + def __isub__(self, val): + print "__isub__ called" + return self + + def __mul__(self, val): + print "__mul__ called" + def __rmul__(self, val): + print "__rmul__ called" + def __imul__(self, val): + print "__imul__ called" + return self + + def __div__(self, val): + print "__div__ called" + def __rdiv__(self, val): + print "__rdiv__ called" + def __idiv__(self, val): + print "__idiv__ called" + return self + + def __mod__(self, val): + print "__mod__ called" + def __rmod__(self, val): + print "__rmod__ called" + def __imod__(self, val): + print "__imod__ called" + return self + + def __pow__(self, val): + print "__pow__ called" + def __rpow__(self, val): + print "__rpow__ called" + def __ipow__(self, val): + print "__ipow__ called" + return self + + def __or__(self, val): + print "__or__ called" + def __ror__(self, val): + print "__ror__ called" + def __ior__(self, val): + print "__ior__ called" + return self + + def __and__(self, val): + print "__and__ called" + def __rand__(self, val): + print "__rand__ called" + def __iand__(self, val): + print "__iand__ called" + return self + + def __xor__(self, val): + print "__xor__ called" + def __rxor__(self, val): + print "__rxor__ called" + def __ixor__(self, val): + print "__ixor__ called" + return self + + def __rshift__(self, val): + print "__rshift__ called" + def __rrshift__(self, val): + print "__rrshift__ called" + def __irshift__(self, val): + print "__irshift__ called" + return self + + def __lshift__(self, val): + print "__lshift__ called" + def __rlshift__(self, val): + print "__rlshift__ called" + def __ilshift__(self, val): + print "__ilshift__ called" + return self + + x = testall() + x + 1 + 1 + x + x += 1 + + x - 1 + 1 - x + x -= 1 + + x * 1 + 1 * x + x *= 1 + + x / 1 + 1 / x + x /= 1 + + x % 1 + 1 % x + x %= 1 + + x ** 1 + 1 ** x + x **= 1 + + x | 1 + 1 | x + x |= 1 + + x & 1 + 1 & x + x &= 1 + + x ^ 1 + 1 ^ x + x ^= 1 + + x >> 1 + 1 >> x + x >>= 1 + + x << 1 + 1 << x + x <<= 1 + diff -crN --exclude=CVS src/Objects/abstract.c src-augassign/Objects/abstract.c *** src/Objects/abstract.c Sun Aug 20 18:57:46 2000 --- src-augassign/Objects/abstract.c Mon Aug 21 17:36:20 2000 *************** *** 610,615 **** --- 610,962 ---- return res; } + /* Binary in-place operators */ + + #define INPLOP(v, w, inplopname, opname, ropname, thisfunc) \ + if (PyInstance_Check(v) || PyInstance_Check(w)) \ + return PyInstance_DoInPlaceOp(v, w, inplopname, opname, ropname, thisfunc) + + #define HASINPLACE(t) PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS) + + PyObject * + PyNumber_InPlaceOr(PyObject *v, PyObject *w) + { + + INPLOP(v, w, "__ior__", "__or__", "__ror__", PyNumber_InPlaceOr); + if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_or) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_or) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for |="); + } + + PyObject * + PyNumber_InPlaceXor(PyObject *v, PyObject *w) + { + + INPLOP(v, w, "__ixor__", "__xor__", "__rxor__", PyNumber_InPlaceXor); + if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_xor) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_xor) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for ^="); + } + + PyObject * + PyNumber_InPlaceAnd(PyObject *v, PyObject *w) + { + + INPLOP(v, w, "__iand__", "__and__", "__rand__", PyNumber_InPlaceAnd); + if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_and) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_and) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for &="); + } + + PyObject * + PyNumber_InPlaceLshift(PyObject *v, PyObject *w) + { + INPLOP(v, w, "__ilshift__", "__lshift__", "__rlshift__", PyNumber_InPlaceLshift); + if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_lshift) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_lshift) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for <<="); + } + + PyObject * + PyNumber_InPlaceRshift(PyObject *v, PyObject *w) + { + INPLOP(v, w, "__irshift__", "__rshift__", "__rrshift__", PyNumber_Rshift); + if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_rshift) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_rshift) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for >>="); + } + + PyObject * + PyNumber_InPlaceAdd(PyObject *v, PyObject *w) + { + PySequenceMethods *m; + + INPLOP(v, w, "__iadd__", "__add__", "__radd__", PyNumber_InPlaceAdd); + m = v->ob_type->tp_as_sequence; + if (m && HASINPLACE(v) && m->sq_inplace_concat) + return (*m->sq_inplace_concat)(v, w); + else if (m && m->sq_concat) + return (*m->sq_concat)(v, w); + else if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_add) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_add) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for +="); + } + + PyObject * + PyNumber_InPlaceSubtract(PyObject *v, PyObject *w) + { + INPLOP(v, w, "__isub__", "__sub__", "__rsub__", PyNumber_InPlaceSubtract); + if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_subtract) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_subtract) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for -="); + } + + PyObject * + PyNumber_InPlaceMultiply(PyObject *v, PyObject *w) + { + PyTypeObject *tp = v->ob_type; + PySequenceMethods *m; + + INPLOP(v, w, "__imul__", "__mul__", "__rmul__", PyNumber_InPlaceMultiply); + + if (tp->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyInstance_Check(v)) { + /* Instances of user-defined classes get their + other argument uncoerced, so they may + implement sequence*number as well as + number*number. */ + Py_INCREF(v); + Py_INCREF(w); + } + else if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_multiply) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_multiply) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + m = tp->tp_as_sequence; + if (m && (m->sq_repeat || (HASINPLACE(v) && m->sq_inplace_repeat))) { + long mul_value; + + if (PyInt_Check(w)) { + mul_value = PyInt_AsLong(w); + } + else if (PyLong_Check(w)) { + mul_value = PyLong_AsLong(w); + if (mul_value == -1 && PyErr_Occurred()) + return NULL; + } + else { + return type_error( + "can't multiply sequence with non-int"); + } + if (m->sq_inplace_repeat) + return (*m->sq_inplace_repeat)(v, (int)mul_value); + else + return (*m->sq_repeat)(v, (int)mul_value); + } + return type_error("bad operand type(s) for *="); + } + + PyObject * + PyNumber_InPlaceDivide(PyObject *v, PyObject *w) + { + INPLOP(v, w, "__idiv__", "__div__", "__rdiv__", PyNumber_InPlaceDivide); + if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_divide) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_divide) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for /="); + } + + PyObject * + PyNumber_InPlaceRemainder(PyObject *v, PyObject *w) + { + if (PyString_Check(v)) + return PyString_Format(v, w); + else if (PyUnicode_Check(v)) + return PyUnicode_Format(v, w); + INPLOP(v, w, "__imod__", "__mod__", "__rmod__", PyNumber_InPlaceRemainder); + if (v->ob_type->tp_as_number != NULL) { + PyObject *x = NULL; + PyObject * (*f)(PyObject *, PyObject *); + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && (f = v->ob_type->tp_as_number->nb_inplace_remainder) != NULL) + x = (*f)(v, w); + else if ((f = v->ob_type->tp_as_number->nb_remainder) != NULL) + x = (*f)(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (f != NULL) + return x; + } + return type_error("bad operand type(s) for %="); + } + + + /* Inplace power, binary and trinary (for API consistency) */ + + static PyObject * + do_inplace_pow(PyObject *v, PyObject *w) + { + PyObject *res; + PyObject *(*f)(PyObject *, PyObject *, PyObject *); + INPLOP(v, w, "__ipow__", "__pow__", "__rpow__", do_pow); + if (v->ob_type->tp_as_number == NULL || + w->ob_type->tp_as_number == NULL) { + PyErr_SetString(PyExc_TypeError, + "**= requires numeric arguments"); + return NULL; + } + if (PyNumber_Coerce(&v, &w) != 0) + return NULL; + if (HASINPLACE(v) && + (f = v->ob_type->tp_as_number->nb_inplace_power) != NULL) + res = (*f)(v, w, Py_None); + else if ((f = v->ob_type->tp_as_number->nb_power) != NULL) + res = (*f)(v, w, Py_None); + else + res = type_error("**= not defined for these operands"); + Py_DECREF(v); + Py_DECREF(w); + return res; + } + + PyObject * + PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z) + { + PyObject *res; + PyObject *v1, *z1, *w2, *z2, *savev; + PyObject * (*f)(PyObject *, PyObject *, PyObject *); + + if (z == Py_None) + return do_inplace_pow(v, w); + /* XXX The ternary version doesn't do class instance coercions */ + if (PyInstance_Check(v)) + return v->ob_type->tp_as_number->nb_inplace_power(v, w, z); + if (v->ob_type->tp_as_number == NULL || + z->ob_type->tp_as_number == NULL || + w->ob_type->tp_as_number == NULL) { + return type_error("inplace pow(x, y, z) requires numeric arguments"); + } + savev = v; + Py_INCREF(savev); + if (PyNumber_Coerce(&v, &w) != 0) { + Py_DECREF(savev); + return NULL; + } + res = NULL; + v1 = v; + z1 = z; + if (PyNumber_Coerce(&v1, &z1) != 0) + goto error2; + w2 = w; + z2 = z1; + if (PyNumber_Coerce(&w2, &z2) != 0) + goto error1; + if (savev == v1 && HASINPLACE(v1) && + (f = v1->ob_type->tp_as_number->nb_inplace_power) != NULL) + res = (*f)(v1, w2, z2); + else if ((f = v1->ob_type->tp_as_number->nb_power) != NULL) + res = (*f)(v1, w2, z2); + else + res = type_error( + "inplace pow(x, y, z) not defined for these operands"); + Py_DECREF(w2); + Py_DECREF(z2); + error1: + Py_DECREF(v1); + Py_DECREF(z1); + error2: + Py_DECREF(savev); + Py_DECREF(v); + Py_DECREF(w); + return res; + } + + /* Unary operators and functions */ PyObject * *************** *** 846,851 **** --- 1193,1232 ---- return null_error(); m = o->ob_type->tp_as_sequence; + if (m && m->sq_repeat) + return m->sq_repeat(o, count); + + return type_error("object can't be repeated"); + } + + PyObject * + PySequence_InPlaceConcat(PyObject *s, PyObject *o) + { + PySequenceMethods *m; + + if (s == NULL || o == NULL) + return null_error(); + + m = s->ob_type->tp_as_sequence; + if (m && HASINPLACE(s) && m->sq_inplace_concat) + return m->sq_inplace_concat(s, o); + if (m && m->sq_concat) + return m->sq_concat(s, o); + + return type_error("object can't be concatenated"); + } + + PyObject * + PySequence_InPlaceRepeat(PyObject *o, int count) + { + PySequenceMethods *m; + + if (o == NULL) + return null_error(); + + m = o->ob_type->tp_as_sequence; + if (m && HASINPLACE(o) && m->sq_inplace_repeat) + return m->sq_inplace_repeat(o, count); if (m && m->sq_repeat) return m->sq_repeat(o, count); diff -crN --exclude=CVS src/Objects/classobject.c src-augassign/Objects/classobject.c *** src/Objects/classobject.c Sun Aug 20 18:57:46 2000 --- src-augassign/Objects/classobject.c Mon Aug 21 14:22:43 2000 *************** *** 1224,1229 **** --- 1224,1248 ---- return NULL; } + /* Implement an in-place operator involving at least one class instance. */ + + PyObject * + PyInstance_DoInPlaceOp(PyObject *v, PyObject *w, char *inplaceopname, + char *opname, char *ropname, + PyObject * (*thisfunc)(PyObject *, PyObject *)) + { + char buf[256]; + PyObject *result = NULL; + if (halfbinop(v, w, inplaceopname, &result, thisfunc, 0) <= 0) + return result; + if (halfbinop(v, w, opname, &result, thisfunc, 0) <= 0) + return result; + if (halfbinop(w, v, ropname, &result, thisfunc, 1) <= 0) + return result; + sprintf(buf, "%s nor %s nor %s defined for these operands", inplaceopname, opname, ropname); + PyErr_SetString(PyExc_TypeError, buf); + return NULL; + } /* Try one half of a binary operator involving a class instance. Return value: diff -crN --exclude=CVS src/Objects/listobject.c src-augassign/Objects/listobject.c *** src/Objects/listobject.c Tue Aug 15 13:11:55 2000 --- src-augassign/Objects/listobject.c Mon Aug 21 14:22:43 2000 *************** *** 492,497 **** --- 492,541 ---- return list_ass_slice((PyListObject *)a, ilow, ihigh, v); } + static PyObject * + list_inplace_repeat(PyListObject *self, int n) + { + PyObject **items; + int size, i, j; + + + size = PyList_GET_SIZE(self); + if (size == 0) { + Py_INCREF(self); + return (PyObject *)self; + } + + items = self->ob_item; + + if (n < 1) { + self->ob_item = NULL; + self->ob_size = 0; + for (i = 0; i < size; i++) + Py_XDECREF(items[i]); + PyMem_DEL(items); + Py_INCREF(self); + return (PyObject *)self; + } + + NRESIZE(items, PyObject*, size*n); + if (items == NULL) { + PyErr_NoMemory(); + goto finally; + } + self->ob_item = items; + for (i = 1; i < n; i++) { /* Start counting at 1, not 0 */ + for (j = 0; j < size; j++) { + PyObject *o = PyList_GET_ITEM(self, j); + Py_INCREF(o); + PyList_SET_ITEM(self, self->ob_size++, o); + } + } + Py_INCREF(self); + return (PyObject *)self; + finally: + return NULL; + } + static int list_ass_item(PyListObject *a, int i, PyObject *v) { *************** *** 552,576 **** return ins(self, (int) self->ob_size, v); } ! static PyObject * ! listextend(PyListObject *self, PyObject *args) { - PyObject *b = NULL, *res = NULL; PyObject **items; int selflen = PyList_GET_SIZE(self); int blen; register int i; - if (!PyArg_ParseTuple(args, "O:extend", &b)) - return NULL; - - b = PySequence_Fast(b, "list.extend() argument must be a sequence"); - if (!b) - return NULL; - if (PyObject_Size(b) == 0) /* short circuit when b is empty */ ! goto ok; if (self == (PyListObject*)b) { /* as in list_ass_slice() we must special case the --- 596,612 ---- return ins(self, (int) self->ob_size, v); } ! static int ! listextend_internal(PyListObject *self, PyObject *b) { PyObject **items; int selflen = PyList_GET_SIZE(self); int blen; register int i; if (PyObject_Size(b) == 0) /* short circuit when b is empty */ ! return 0; if (self == (PyListObject*)b) { /* as in list_ass_slice() we must special case the *************** *** 582,588 **** Py_DECREF(b); b = PyList_New(selflen); if (!b) ! return NULL; for (i = 0; i < selflen; i++) { PyObject *o = PyList_GET_ITEM(self, i); Py_INCREF(o); --- 618,624 ---- Py_DECREF(b); b = PyList_New(selflen); if (!b) ! return -1; for (i = 0; i < selflen; i++) { PyObject *o = PyList_GET_ITEM(self, i); Py_INCREF(o); *************** *** 597,604 **** NRESIZE(items, PyObject*, selflen + blen); if (items == NULL) { PyErr_NoMemory(); ! goto failed; } self->ob_item = items; /* populate the end of self with b's items */ --- 633,642 ---- NRESIZE(items, PyObject*, selflen + blen); if (items == NULL) { PyErr_NoMemory(); ! Py_DECREF(b); ! return -1; } + self->ob_item = items; /* populate the end of self with b's items */ *************** *** 607,620 **** Py_INCREF(o); PyList_SET_ITEM(self, self->ob_size++, o); } - ok: - res = Py_None; - Py_INCREF(res); - failed: Py_DECREF(b); ! return res; } static PyObject * listpop(PyListObject *self, PyObject *args) --- 645,688 ---- Py_INCREF(o); PyList_SET_ITEM(self, self->ob_size++, o); } Py_DECREF(b); ! return 0; ! } ! ! ! static PyObject * ! list_inplace_concat(PyListObject *self, PyObject *other) ! { ! other = PySequence_Fast(other, "argument to += must be a sequence"); ! if (!other) ! return NULL; ! ! if (listextend_internal(self, other) < 0) ! return NULL; ! ! Py_INCREF(self); ! return (PyObject *)self; } + static PyObject * + listextend(PyListObject *self, PyObject *args) + { + + PyObject *b; + + if (!PyArg_ParseTuple(args, "O:extend", &b)) + return NULL; + + b = PySequence_Fast(b, "list.extend() argument must be a sequence"); + if (!b) + return NULL; + + if (listextend_internal(self, b) < 0) + return NULL; + + Py_INCREF(Py_None); + return Py_None; + } static PyObject * listpop(PyListObject *self, PyObject *args) *************** *** 1403,1408 **** --- 1471,1478 ---- (intobjargproc)list_ass_item, /*sq_ass_item*/ (intintobjargproc)list_ass_slice, /*sq_ass_slice*/ (objobjproc)list_contains, /*sq_contains*/ + (binaryfunc)list_inplace_concat, /*sq_inplace_concat*/ + (intargfunc)list_inplace_repeat, /*sq_inplace_repeat*/ }; PyTypeObject PyList_Type = { diff -crN --exclude=CVS src/Parser/grammar.c src-augassign/Parser/grammar.c *** src/Parser/grammar.c Sat Jul 22 21:20:54 2000 --- src-augassign/Parser/grammar.c Mon Aug 21 14:22:43 2000 *************** *** 211,216 **** --- 211,228 ---- printf("Unknown OP label %s\n", lb->lb_str); } + else if (lb->lb_str[2] && lb->lb_str[3] && lb->lb_str[4] == lb->lb_str[0]) { + int type = (int) PyToken_ThreeChars(lb->lb_str[1], + lb->lb_str[2], + lb->lb_str[3]); + if (type != OP) { + lb->lb_type = type; + lb->lb_str = NULL; + } + else + printf("Unknown OP label %s\n", + lb->lb_str); + } else printf("Can't translate STRING label %s\n", lb->lb_str); diff -crN --exclude=CVS src/Parser/tokenizer.c src-augassign/Parser/tokenizer.c *** src/Parser/tokenizer.c Sat Jul 22 21:20:54 2000 --- src-augassign/Parser/tokenizer.c Mon Aug 21 14:22:43 2000 *************** *** 78,83 **** --- 78,94 ---- "LEFTSHIFT", "RIGHTSHIFT", "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", /* This table must match the #defines in token.h! */ "OP", "", *************** *** 388,402 **** --- 399,489 ---- case '>': return RIGHTSHIFT; } break; + case '+': + switch (c2) { + case '=': return PLUSEQUAL; + } + break; + case '-': + switch (c2) { + case '=': return MINEQUAL; + } + break; case '*': switch (c2) { case '*': return DOUBLESTAR; + case '=': return STAREQUAL; + } + break; + case '/': + switch (c2) { + case '=': return SLASHEQUAL; + } + break; + case '|': + switch (c2) { + case '=': return VBAREQUAL; + } + break; + case '%': + switch (c2) { + case '=': return PERCENTEQUAL; + } + break; + case '&': + switch (c2) { + case '=': return AMPEREQUAL; + } + break; + case '^': + switch (c2) { + case '=': return CIRCUMFLEXEQUAL; } break; } return OP; } + int + PyToken_ThreeChars(int c1, int c2, int c3) + { + switch (c1) { + case '<': + switch (c2) { + case '<': + switch (c3) { + case '=': + return LEFTSHIFTEQUAL; + break; + } + break; + } + break; + case '>': + switch (c2) { + case '>': + switch (c3) { + case '=': + return RIGHTSHIFTEQUAL; + break; + } + break; + } + break; + case '*': + switch (c2) { + case '*': + switch (c3) { + case '=': + return DOUBLESTAREQUAL; + break; + } + break; + } + break; + } + return OP; + } static int indenterror(struct tok_state *tok) *************** *** 770,775 **** --- 857,869 ---- int c2 = tok_nextc(tok); int token = PyToken_TwoChars(c, c2); if (token != OP) { + int c3 = tok_nextc(tok); + int token3 = PyToken_ThreeChars(c, c2, c3); + if (token3 != OP) { + token = token3; + } else { + tok_backup(tok, c3); + } *p_start = tok->start; *p_end = tok->cur; return token; diff -crN --exclude=CVS src/Python/ceval.c src-augassign/Python/ceval.c *** src/Python/ceval.c Tue Aug 22 17:40:13 2000 --- src-augassign/Python/ceval.c Mon Aug 21 18:03:17 2000 *************** *** 668,679 **** --- 668,736 ---- PUSH(w); continue; + case ROT_FOUR: + u = POP(); + v = POP(); + w = POP(); + x = POP(); + PUSH(u); + PUSH(x); + PUSH(w); + PUSH(v); + continue; + case DUP_TOP: v = TOP(); Py_INCREF(v); PUSH(v); continue; + case DUP_TOPX: + switch (oparg) { + case 5: + case 4: + case 3: + case 2: + case 1: + x = POP(); + if (oparg == 1) break; + w = POP(); + if (oparg == 2) break; + v = POP(); + if (oparg == 3) break; + u = POP(); + if (oparg == 4) break; + t = POP(); + break; + default: + fprintf(stderr, "Invalid argument to DUP_TOPX: %d!\n", oparg); + PyErr_SetString(PyExc_SystemError, + "invalid argument to DUP_TOPX"); + x = NULL; + } + if (x == NULL) + break; + switch (oparg) { + case 5: PUSH(t); + Py_INCREF(t); /* Fallthrough */ + case 4: PUSH(u); + Py_INCREF(u); /* Fallthrough */ + case 3: PUSH(v); + Py_INCREF(v); /* Fallthrough */ + case 2: PUSH(w); + Py_INCREF(w); /* Fallthrough */ + case 1: PUSH(x); + Py_INCREF(x); /* Fallthrough */ + } + switch (oparg) { + case 5: PUSH(t); /* Fallthrough */ + case 4: PUSH(u); /* Fallthrough */ + case 3: PUSH(v); /* Fallthrough */ + case 2: PUSH(w); /* Fallthrough */ + case 1: PUSH(x); /* Fallthrough */ + } + continue; + case UNARY_POSITIVE: v = POP(); x = PyNumber_Positive(v); *************** *** 889,895 **** --- 946,1092 ---- PUSH(x); if (x != NULL) continue; break; + + case INPLACE_POWER: + w = POP(); + v = POP(); + x = PyNumber_InPlacePower(v, w, Py_None); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_MULTIPLY: + w = POP(); + v = POP(); + x = PyNumber_InPlaceMultiply(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_DIVIDE: + w = POP(); + v = POP(); + x = PyNumber_InPlaceDivide(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_MODULO: + w = POP(); + v = POP(); + x = PyNumber_InPlaceRemainder(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + case INPLACE_ADD: + w = POP(); + v = POP(); + if (PyInt_Check(v) && PyInt_Check(w)) { + /* INLINE: int + int */ + register long a, b, i; + a = PyInt_AS_LONG(v); + b = PyInt_AS_LONG(w); + i = a + b; + if ((i^a) < 0 && (i^b) < 0) { + PyErr_SetString(PyExc_OverflowError, + "integer addition"); + x = NULL; + } + else + x = PyInt_FromLong(i); + } + else + x = PyNumber_InPlaceAdd(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_SUBTRACT: + w = POP(); + v = POP(); + if (PyInt_Check(v) && PyInt_Check(w)) { + /* INLINE: int - int */ + register long a, b, i; + a = PyInt_AS_LONG(v); + b = PyInt_AS_LONG(w); + i = a - b; + if ((i^a) < 0 && (i^~b) < 0) { + PyErr_SetString(PyExc_OverflowError, + "integer subtraction"); + x = NULL; + } + else + x = PyInt_FromLong(i); + } + else + x = PyNumber_InPlaceSubtract(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_LSHIFT: + w = POP(); + v = POP(); + x = PyNumber_InPlaceLshift(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_RSHIFT: + w = POP(); + v = POP(); + x = PyNumber_InPlaceRshift(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_AND: + w = POP(); + v = POP(); + x = PyNumber_InPlaceAnd(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_XOR: + w = POP(); + v = POP(); + x = PyNumber_InPlaceXor(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + + case INPLACE_OR: + w = POP(); + v = POP(); + x = PyNumber_InPlaceOr(v, w); + Py_DECREF(v); + Py_DECREF(w); + PUSH(x); + if (x != NULL) continue; + break; + case SLICE+0: case SLICE+1: case SLICE+2: *************** *** 1062,1067 **** --- 1259,1268 ---- stream = NULL; break; + + #ifdef CASE_TOO_BIG + default: switch (opcode) { + #endif case BREAK_LOOP: why = WHY_BREAK; break; *************** *** 1179,1188 **** PyErr_SetObject(PyExc_NameError, w); break; - #ifdef CASE_TOO_BIG - default: switch (opcode) { - #endif - case UNPACK_SEQUENCE: v = POP(); if (PyTuple_Check(v)) { --- 1380,1385 ---- diff -crN --exclude=CVS src/Python/compile.c src-augassign/Python/compile.c *** src/Python/compile.c Tue Aug 22 17:40:13 2000 --- src-augassign/Python/compile.c Tue Aug 22 14:08:19 2000 *************** *** 388,399 **** static void com_list_iter(struct compiling *, node *, node *, char *); static int com_argdefs(struct compiling *, node *); static int com_newlocal(struct compiling *, char *); ! static void com_assign(struct compiling *, node *, int); static PyCodeObject *icompile(struct _node *, struct compiling *); static PyCodeObject *jcompile(struct _node *, char *, struct compiling *); static PyObject *parsestrplus(node *); static PyObject *parsestr(char *); static int com_init(struct compiling *c, char *filename) --- 388,401 ---- static void com_list_iter(struct compiling *, node *, node *, char *); static int com_argdefs(struct compiling *, node *); static int com_newlocal(struct compiling *, char *); ! static void com_assign(struct compiling *, node *, int, node *); ! static void com_assign_name(struct compiling *, node *, int); static PyCodeObject *icompile(struct _node *, struct compiling *); static PyCodeObject *jcompile(struct _node *, char *, struct compiling *); static PyObject *parsestrplus(node *); static PyObject *parsestr(char *); + static node *get_rawdocstring(node *); static int com_init(struct compiling *c, char *filename) *************** *** 979,985 **** com_addoparg(c, SET_LINENO, n->n_lineno); com_addfwref(c, FOR_LOOP, &anchor); com_push(c, 1); ! com_assign(c, CHILD(n, 1), OP_ASSIGN); c->c_loops++; com_list_iter(c, n, e, t); c->c_loops--; --- 981,987 ---- com_addoparg(c, SET_LINENO, n->n_lineno); com_addfwref(c, FOR_LOOP, &anchor); com_push(c, 1); ! com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL); c->c_loops++; com_list_iter(c, n, e, t); c->c_loops--; *************** *** 1187,1192 **** --- 1189,1247 ---- } static void + com_augassign_slice(struct compiling *c, node *n, int opcode, node *augn) + { + if (NCH(n) == 1) { + com_addbyte(c, DUP_TOP); + com_push(c, 1); + com_addbyte(c, SLICE); + com_node(c, augn); + com_addbyte(c, opcode); + com_pop(c, 1); + com_addbyte(c, ROT_TWO); + com_addbyte(c, STORE_SLICE); + com_pop(c, 2); + } else if (NCH(n) == 2 && TYPE(CHILD(n, 0)) != COLON) { + com_node(c, CHILD(n, 0)); + com_addoparg(c, DUP_TOPX, 2); + com_push(c, 2); + com_addbyte(c, SLICE+1); + com_pop(c, 1); + com_node(c, augn); + com_addbyte(c, opcode); + com_pop(c, 1); + com_addbyte(c, ROT_THREE); + com_addbyte(c, STORE_SLICE+1); + com_pop(c, 3); + } else if (NCH(n) == 2) { + com_node(c, CHILD(n, 1)); + com_addoparg(c, DUP_TOPX, 2); + com_push(c, 2); + com_addbyte(c, SLICE+2); + com_pop(c, 1); + com_node(c, augn); + com_addbyte(c, opcode); + com_pop(c, 1); + com_addbyte(c, ROT_THREE); + com_addbyte(c, STORE_SLICE+2); + com_pop(c, 3); + } else { + com_node(c, CHILD(n, 0)); + com_node(c, CHILD(n, 2)); + com_addoparg(c, DUP_TOPX, 3); + com_push(c, 3); + com_addbyte(c, SLICE+3); + com_pop(c, 2); + com_node(c, augn); + com_addbyte(c, opcode); + com_pop(c, 1); + com_addbyte(c, ROT_FOUR); + com_addbyte(c, STORE_SLICE+3); + com_pop(c, 4); + } + } + + static void com_argument(struct compiling *c, node *n, PyObject **pkeywords) { node *m; *************** *** 1360,1366 **** } static void ! com_subscriptlist(struct compiling *c, node *n, int assigning) { int i, op; REQ(n, subscriptlist); --- 1415,1421 ---- } static void ! com_subscriptlist(struct compiling *c, node *n, int assigning, node *augn) { int i, op; REQ(n, subscriptlist); *************** *** 1372,1382 **** || (NCH(sub) > 1 && TYPE(CHILD(sub, 1)) == COLON)) && (TYPE(CHILD(sub,NCH(sub)-1)) != sliceop)) { ! if (assigning == OP_APPLY) op = SLICE; ! else ! op = ((assigning == OP_ASSIGN) ? ! STORE_SLICE : DELETE_SLICE); com_slice(c, sub, op); if (op == STORE_SLICE) com_pop(c, 2); --- 1427,1446 ---- || (NCH(sub) > 1 && TYPE(CHILD(sub, 1)) == COLON)) && (TYPE(CHILD(sub,NCH(sub)-1)) != sliceop)) { ! switch (assigning) { ! case OP_DELETE: ! op = DELETE_SLICE; ! break; ! case OP_ASSIGN: ! op = STORE_SLICE; ! break; ! case OP_APPLY: op = SLICE; ! break; ! default: ! com_augassign_slice(c, sub, assigning, augn); ! return; ! } com_slice(c, sub, op); if (op == STORE_SLICE) com_pop(c, 2); *************** *** 1394,1410 **** com_addoparg(c, BUILD_TUPLE, i); com_pop(c, i-1); } ! if (assigning == OP_APPLY) { ! op = BINARY_SUBSCR; ! i = 1; ! } ! else if (assigning == OP_ASSIGN) { op = STORE_SUBSCR; i = 3; } ! else { ! op = DELETE_SUBSCR; ! i = 2; } com_addbyte(c, op); com_pop(c, i); --- 1458,1487 ---- com_addoparg(c, BUILD_TUPLE, i); com_pop(c, i-1); } ! switch (assigning) { ! case OP_DELETE: ! op = DELETE_SUBSCR; ! i = 2; ! break; ! default: ! case OP_ASSIGN: op = STORE_SUBSCR; i = 3; + break; + case OP_APPLY: + op = BINARY_SUBSCR; + i = 1; + break; } ! if (assigning > OP_APPLY) { ! com_addoparg(c, DUP_TOPX, 2); ! com_push(c, 2); ! com_addbyte(c, BINARY_SUBSCR); ! com_pop(c, 1); ! com_node(c, augn); ! com_addbyte(c, assigning); ! com_pop(c, 1); ! com_addbyte(c, ROT_THREE); } com_addbyte(c, op); com_pop(c, i); *************** *** 1422,1428 **** com_select_member(c, CHILD(n, 1)); break; case LSQB: ! com_subscriptlist(c, CHILD(n, 1), OP_APPLY); break; default: com_error(c, PyExc_SystemError, --- 1499,1505 ---- com_select_member(c, CHILD(n, 1)); break; case LSQB: ! com_subscriptlist(c, CHILD(n, 1), OP_APPLY, NULL); break; default: com_error(c, PyExc_SystemError, *************** *** 1816,1823 **** /* Begin of assignment compilation */ ! static void com_assign_name(struct compiling *, node *, int); ! static void com_assign(struct compiling *, node *, int); static void com_assign_attr(struct compiling *c, node *n, int assigning) --- 1893,1913 ---- /* Begin of assignment compilation */ ! ! static void ! com_augassign_attr(struct compiling *c, node *n, int opcode, node *augn) ! { ! com_addbyte(c, DUP_TOP); ! com_push(c, 1); ! com_addopname(c, LOAD_ATTR, n); ! com_pop(c, 1); ! com_node(c, augn); ! com_addbyte(c, opcode); ! com_pop(c, 1); ! com_addbyte(c, ROT_TWO); ! com_addopname(c, STORE_ATTR, n); ! com_pop(c, 2); ! } static void com_assign_attr(struct compiling *c, node *n, int assigning) *************** *** 1827,1833 **** } static void ! com_assign_trailer(struct compiling *c, node *n, int assigning) { REQ(n, trailer); switch (TYPE(CHILD(n, 0))) { --- 1917,1923 ---- } static void ! com_assign_trailer(struct compiling *c, node *n, int assigning, node *augn) { REQ(n, trailer); switch (TYPE(CHILD(n, 0))) { *************** *** 1836,1845 **** "can't assign to function call"); break; case DOT: /* '.' NAME */ ! com_assign_attr(c, CHILD(n, 1), assigning); break; case LSQB: /* '[' subscriptlist ']' */ ! com_subscriptlist(c, CHILD(n, 1), assigning); break; default: com_error(c, PyExc_SystemError, "unknown trailer type"); --- 1926,1938 ---- "can't assign to function call"); break; case DOT: /* '.' NAME */ ! if (assigning > OP_APPLY) ! com_augassign_attr(c, CHILD(n, 1), assigning, augn); ! else ! com_assign_attr(c, CHILD(n, 1), assigning); break; case LSQB: /* '[' subscriptlist ']' */ ! com_subscriptlist(c, CHILD(n, 1), assigning, augn); break; default: com_error(c, PyExc_SystemError, "unknown trailer type"); *************** *** 1858,1864 **** com_push(c, i-1); } for (i = 0; i < NCH(n); i += 2) ! com_assign(c, CHILD(n, i), assigning); } static void --- 1951,1969 ---- com_push(c, i-1); } for (i = 0; i < NCH(n); i += 2) ! com_assign(c, CHILD(n, i), assigning, NULL); ! } ! ! static void ! com_augassign_name(struct compiling *c, node *n, int opcode, node *augn) ! { ! REQ(n, NAME); ! com_addopname(c, LOAD_NAME, n); ! com_push(c, 1); ! com_node(c, augn); ! com_addbyte(c, opcode); ! com_pop(c, 1); ! com_assign_name(c, n, OP_ASSIGN); } static void *************** *** 1871,1877 **** } static void ! com_assign(struct compiling *c, node *n, int assigning) { /* Loop to avoid trivial recursion */ for (;;) { --- 1976,1982 ---- } static void ! com_assign(struct compiling *c, node *n, int assigning, node *augn) { /* Loop to avoid trivial recursion */ for (;;) { *************** *** 1880,1885 **** --- 1985,1995 ---- case exprlist: case testlist: if (NCH(n) > 1) { + if (assigning > OP_APPLY) { + com_error(c, PyExc_SyntaxError, + "augmented assign to tuple not possible"); + return; + } com_assign_sequence(c, n, assigning); return; } *************** *** 1924,1930 **** com_apply_trailer(c, CHILD(n, i)); } /* NB i is still alive */ com_assign_trailer(c, ! CHILD(n, i), assigning); return; } n = CHILD(n, 0); --- 2034,2040 ---- com_apply_trailer(c, CHILD(n, i)); } /* NB i is still alive */ com_assign_trailer(c, ! CHILD(n, i), assigning, augn); return; } n = CHILD(n, 0); *************** *** 1940,1945 **** --- 2050,2060 ---- "can't assign to ()"); return; } + if (assigning > OP_APPLY) { + com_error(c, PyExc_SyntaxError, + "augmented assign to tuple not possible"); + return; + } break; case LSQB: n = CHILD(n, 1); *************** *** 1948,1957 **** "can't assign to []"); return; } com_assign_sequence(c, n, assigning); return; case NAME: ! com_assign_name(c, CHILD(n, 0), assigning); return; default: com_error(c, PyExc_SyntaxError, --- 2063,2082 ---- "can't assign to []"); return; } + if (assigning > OP_APPLY) { + com_error(c, PyExc_SyntaxError, + "augmented assign to list not possible"); + return; + } com_assign_sequence(c, n, assigning); return; case NAME: ! if (assigning > OP_APPLY) ! com_augassign_name(c, CHILD(n, 0), ! assigning, augn); ! else ! com_assign_name(c, CHILD(n, 0), ! assigning); return; default: com_error(c, PyExc_SyntaxError, *************** *** 1975,2005 **** } } ! /* Forward */ static node *get_rawdocstring(node *); static void com_expr_stmt(struct compiling *c, node *n) { ! REQ(n, expr_stmt); /* testlist ('=' testlist)* */ /* Forget it if we have just a doc string here */ if (!c->c_interactive && NCH(n) == 1 && get_rawdocstring(n) != NULL) return; ! com_node(c, CHILD(n, NCH(n)-1)); ! if (NCH(n) == 1) { if (c->c_interactive) com_addbyte(c, PRINT_EXPR); else com_addbyte(c, POP_TOP); com_pop(c, 1); } else { int i; for (i = 0; i < NCH(n)-2; i+=2) { if (i+2 < NCH(n)-2) { com_addbyte(c, DUP_TOP); com_push(c, 1); } ! com_assign(c, CHILD(n, i), OP_ASSIGN); } } } --- 2100,2160 ---- } } ! static void ! com_augassign(struct compiling *c, node *n) ! { ! int opcode; ! ! switch (STR(CHILD(CHILD(n, 1), 0))[0]) { ! case '+': opcode = INPLACE_ADD; break; ! case '-': opcode = INPLACE_SUBTRACT; break; ! case '/': opcode = INPLACE_DIVIDE; break; ! case '%': opcode = INPLACE_MODULO; break; ! case '<': opcode = INPLACE_LSHIFT; break; ! case '>': opcode = INPLACE_RSHIFT; break; ! case '&': opcode = INPLACE_AND; break; ! case '^': opcode = INPLACE_XOR; break; ! case '|': opcode = INPLACE_OR; break; ! case '*': ! if (STR(CHILD(CHILD(n, 1), 0))[1] == '*') ! opcode = INPLACE_POWER; ! else ! opcode = INPLACE_MULTIPLY; ! break; ! default: ! com_error(c, PyExc_SystemError, "com_augassign: bad operator"); ! return; ! } ! com_assign(c, CHILD(n, 0), opcode, CHILD(n, 2)); ! } static void com_expr_stmt(struct compiling *c, node *n) { ! REQ(n, expr_stmt); ! /* testlist (('=' testlist)* | augassign testlist) */ /* Forget it if we have just a doc string here */ if (!c->c_interactive && NCH(n) == 1 && get_rawdocstring(n) != NULL) return; ! if (NCH(n) == 1) { ! com_node(c, CHILD(n, NCH(n)-1)); if (c->c_interactive) com_addbyte(c, PRINT_EXPR); else com_addbyte(c, POP_TOP); com_pop(c, 1); } + else if (TYPE(CHILD(n,1)) == augassign) + com_augassign(c, n); else { int i; + com_node(c, CHILD(n, NCH(n)-1)); for (i = 0; i < NCH(n)-2; i+=2) { if (i+2 < NCH(n)-2) { com_addbyte(c, DUP_TOP); com_push(c, 1); } ! com_assign(c, CHILD(n, i), OP_ASSIGN, NULL); } } } *************** *** 2456,2462 **** com_addoparg(c, SET_LINENO, n->n_lineno); com_addfwref(c, FOR_LOOP, &anchor); com_push(c, 1); ! com_assign(c, CHILD(n, 1), OP_ASSIGN); c->c_loops++; com_node(c, CHILD(n, 5)); c->c_loops--; --- 2611,2617 ---- com_addoparg(c, SET_LINENO, n->n_lineno); com_addfwref(c, FOR_LOOP, &anchor); com_push(c, 1); ! com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL); c->c_loops++; com_node(c, CHILD(n, 5)); c->c_loops--; *************** *** 2578,2584 **** com_addbyte(c, POP_TOP); com_pop(c, 1); if (NCH(ch) > 3) ! com_assign(c, CHILD(ch, 3), OP_ASSIGN); else { com_addbyte(c, POP_TOP); com_pop(c, 1); --- 2733,2739 ---- com_addbyte(c, POP_TOP); com_pop(c, 1); if (NCH(ch) > 3) ! com_assign(c, CHILD(ch, 3), OP_ASSIGN, NULL); else { com_addbyte(c, POP_TOP); com_pop(c, 1); *************** *** 2924,2930 **** com_print_stmt(c, n); break; case del_stmt: /* 'del' exprlist */ ! com_assign(c, CHILD(n, 1), OP_DELETE); break; case pass_stmt: break; --- 3079,3085 ---- com_print_stmt(c, n); break; case del_stmt: /* 'del' exprlist */ ! com_assign(c, CHILD(n, 1), OP_DELETE, NULL); break; case pass_stmt: break; diff -crN --exclude=CVS src/Python/import.c src-augassign/Python/import.c *** src/Python/import.c Tue Aug 22 17:40:14 2000 --- src-augassign/Python/import.c Tue Aug 22 14:09:13 2000 *************** *** 66,72 **** /* XXX Perhaps the magic number should be frozen and a version field added to the .pyc file header? */ /* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */ ! #define MAGIC (50821 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the --- 66,72 ---- /* XXX Perhaps the magic number should be frozen and a version field added to the .pyc file header? */ /* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */ ! #define MAGIC (50822 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the