Skip to content

Commit

Permalink
@ binary operator, PyUnicode_FormatPrime
Browse files Browse the repository at this point in the history
  • Loading branch information
jcsalterego committed Jun 21, 2009
1 parent a91489a commit 5c8bdf7
Show file tree
Hide file tree
Showing 15 changed files with 134 additions and 8 deletions.
10 changes: 10 additions & 0 deletions py3k/Doc/library/dis.rst
Expand Up @@ -228,6 +228,11 @@ result back on the stack.
Implements ``TOS = TOS1 % TOS``.


.. opcode:: BINARY_AT ()

Implements ``TOS = TOS1 @ TOS``.


.. opcode:: BINARY_ADD ()

Implements ``TOS = TOS1 + TOS``.
Expand Down Expand Up @@ -299,6 +304,11 @@ the original TOS1.
Implements in-place ``TOS = TOS1 % TOS``.


.. opcode:: INPLACE_AT ()

Implements in-place ``TOS = TOS1 @ TOS``.


.. opcode:: INPLACE_ADD ()

Implements in-place ``TOS = TOS1 + TOS``.
Expand Down
4 changes: 2 additions & 2 deletions py3k/Grammar/Grammar
Expand Up @@ -40,7 +40,7 @@ small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
expr_stmt: testlist (augassign (yield_expr|testlist) |
('=' (yield_expr|testlist))*)
augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
'<<=' | '>>=' | '**=' | '//=' | '@=')
# For normal assignments, additional restrictions enforced by the interpreter
del_stmt: 'del' exprlist
pass_stmt: 'pass'
Expand Down Expand Up @@ -94,7 +94,7 @@ xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)*
shift_expr: arith_expr (('<<'|'>>') arith_expr)*
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'/'|'%'|'//') factor)*
term: factor (('*'|'/'|'%'|'@'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom trailer* ['**' factor]
atom: ('(' [yield_expr|testlist_comp] ')' |
Expand Down
4 changes: 2 additions & 2 deletions py3k/Include/Python-ast.h
Expand Up @@ -16,8 +16,8 @@ typedef struct _slice *slice_ty;
typedef enum _boolop { And=1, Or=2 } boolop_ty;

typedef enum _operator { Add=1, Sub=2, Mult=3, Div=4, Mod=5, Pow=6, LShift=7,
RShift=8, BitOr=9, BitXor=10, BitAnd=11, FloorDiv=12 }
operator_ty;
RShift=8, BitOr=9, BitXor=10, BitAnd=11, FloorDiv=12,
At=13 } operator_ty;

typedef enum _unaryop { Invert=1, Not=2, UAdd=3, USub=4 } unaryop_ty;

Expand Down
2 changes: 2 additions & 0 deletions py3k/Include/opcode.h
Expand Up @@ -33,6 +33,8 @@ extern "C" {
#define BINARY_TRUE_DIVIDE 27
#define INPLACE_FLOOR_DIVIDE 28
#define INPLACE_TRUE_DIVIDE 29
#define BINARY_AT 30
#define INPLACE_AT 31

#define STORE_MAP 54
#define INPLACE_ADD 55
Expand Down
1 change: 1 addition & 0 deletions py3k/Include/token.h
Expand Up @@ -64,6 +64,7 @@ extern "C" {
#define OP 53
#define ERRORTOKEN 54
#define N_TOKENS 55
#define ATEQUAL 56

/* Special definitions for cooperation with parser */

Expand Down
7 changes: 7 additions & 0 deletions py3k/Include/unicodeobject.h
Expand Up @@ -189,6 +189,7 @@ typedef PY_UNICODE_TYPE Py_UNICODE;
# define PyUnicode_EncodeUnicodeEscape PyUnicodeUCS2_EncodeUnicodeEscape
# define PyUnicode_Find PyUnicodeUCS2_Find
# define PyUnicode_Format PyUnicodeUCS2_Format
# define PyUnicode_FormatPrime PyUnicodeUCS2_FormatPrime
# define PyUnicode_FromEncodedObject PyUnicodeUCS2_FromEncodedObject
# define PyUnicode_FromFormat PyUnicodeUCS2_FromFormat
# define PyUnicode_FromFormatV PyUnicodeUCS2_FromFormatV
Expand Down Expand Up @@ -288,6 +289,7 @@ typedef PY_UNICODE_TYPE Py_UNICODE;
# define PyUnicode_EncodeUnicodeEscape PyUnicodeUCS4_EncodeUnicodeEscape
# define PyUnicode_Find PyUnicodeUCS4_Find
# define PyUnicode_Format PyUnicodeUCS4_Format
# define PyUnicode_FormatPrime PyUnicodeUCS4_FormatPrime
# define PyUnicode_FromEncodedObject PyUnicodeUCS4_FromEncodedObject
# define PyUnicode_FromFormat PyUnicodeUCS4_FromFormat
# define PyUnicode_FromFormatV PyUnicodeUCS4_FromFormatV
Expand Down Expand Up @@ -1464,6 +1466,11 @@ PyAPI_FUNC(PyObject *) PyUnicode_Format(
PyObject *args /* Argument tuple or dictionary */
);

PyAPI_FUNC(PyObject *) PyUnicode_FormatPrime(
PyObject *format, /* Format string */
PyObject *args /* Argument tuple or dictionary */
);

/* Checks whether element is contained in container and return 1/0
accordingly.
Expand Down
2 changes: 2 additions & 0 deletions py3k/Lib/opcode.py
Expand Up @@ -68,6 +68,8 @@ def jabs_op(name, op):
def_op('BINARY_TRUE_DIVIDE', 27)
def_op('INPLACE_FLOOR_DIVIDE', 28)
def_op('INPLACE_TRUE_DIVIDE', 29)
def_op('BINARY_AT', 30)
def_op('INPLACE_AT', 31)

def_op('STORE_MAP', 54)
def_op('INPLACE_ADD', 55)
Expand Down
4 changes: 3 additions & 1 deletion py3k/Modules/parsermodule.c
Expand Up @@ -1547,6 +1547,7 @@ validate_expr_stmt(node *tree)
|| strcmp(s, "/=") == 0
|| strcmp(s, "//=") == 0
|| strcmp(s, "%=") == 0
|| strcmp(s, "@=") == 0
|| strcmp(s, "&=") == 0
|| strcmp(s, "|=") == 0
|| strcmp(s, "^=") == 0
Expand Down Expand Up @@ -2251,7 +2252,8 @@ validate_term(node *tree)
res = (((TYPE(CHILD(tree, pos)) == STAR)
|| (TYPE(CHILD(tree, pos)) == SLASH)
|| (TYPE(CHILD(tree, pos)) == DOUBLESLASH)
|| (TYPE(CHILD(tree, pos)) == PERCENT))
|| (TYPE(CHILD(tree, pos)) == PERCENT)
|| (TYPE(CHILD(tree, pos)) == AT))
&& validate_factor(CHILD(tree, pos + 1)));

return (res);
Expand Down
65 changes: 65 additions & 0 deletions py3k/Objects/unicodeobject.c
Expand Up @@ -9067,6 +9067,71 @@ formatchar(Py_UNICODE *buf,
return -1;
}

PyObject *
PyUnicode_FormatPrime(PyObject *format, PyObject *args)
{
Py_ssize_t arglen;
PyObject *dict, *last_item, *retval, *tuple;
int args_ref = 0, tuple_ref = 0;

if (format == NULL || args == NULL) {
PyErr_BadInternalCall();
return NULL;
} else if (!PyUnicode_Check(format)) {
PyErr_Format(PyExc_TypeError,
"unsupported operand type(s) for %.100s: "
"'%.100s' and '%.100s'",
"@",
format->ob_type->tp_name,
args->ob_type->tp_name);
return NULL;
}

/* default values */
tuple = args;
dict = NULL;

if (PyTuple_Check(args)) {
arglen = PyTuple_Size(args);

if (arglen > 1) {
/* check for existence of dict at end */
last_item = PyTuple_GetItem(args, arglen - 1);

if (PyDict_CheckExact(last_item)) {
dict = last_item;

/* clone n - 1 elements of an n-sized tuple...
* does this introduce a memory leak?
*/
tuple = PyTuple_GetSlice(args, 0, arglen - 1);
args_ref = 1;
}
}
}
else if (PyDict_Check(args)) {
tuple = PyTuple_New(0);
if (!tuple)
return NULL;
dict = args;
}
else {
/* pass as one-length tuple */
tuple = PyTuple_New(1);
tuple_ref = 1;
PyTuple_SetItem(tuple, 0, args);
Py_INCREF(args);
}

retval = do_string_format(format, tuple, dict);
if (tuple_ref)
Py_DECREF(tuple);
if (args_ref)
Py_DECREF(args);
return retval;
}


/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)
FORMATBUFLEN is the length of the buffer in which chars are formatted.
*/
Expand Down
1 change: 1 addition & 0 deletions py3k/Parser/Python.asdl
Expand Up @@ -93,6 +93,7 @@ module Python version "$Revision: 67616 $"

operator = Add | Sub | Mult | Div | Mod | Pow | LShift
| RShift | BitOr | BitXor | BitAnd | FloorDiv
| At

unaryop = Invert | Not | UAdd | USub

Expand Down
8 changes: 7 additions & 1 deletion py3k/Parser/tokenizer.c
Expand Up @@ -103,7 +103,8 @@ char *_PyParser_TokenNames[] = {
/* This table must match the #defines in token.h! */
"OP",
"<ERRORTOKEN>",
"<N_TOKENS>"
"<N_TOKENS>",
"ATEQUAL"
};


Expand Down Expand Up @@ -1084,6 +1085,11 @@ PyToken_TwoChars(int c1, int c2)
case '=': return PERCENTEQUAL;
}
break;
case '@':
switch (c2) {
case '=': return ATEQUAL;
}
break;
case '&':
switch (c2) {
case '=': return AMPEREQUAL;
Expand Down
4 changes: 4 additions & 0 deletions py3k/Python/ast.c
Expand Up @@ -348,6 +348,8 @@ get_operator(const node *n)
return FloorDiv;
case PERCENT:
return Mod;
case AT:
return At;
default:
return (operator_ty)0;
}
Expand Down Expand Up @@ -517,6 +519,8 @@ ast_for_augassign(struct compiling *c, const node *n)
return Div;
case '%':
return Mod;
case '@':
return At;
case '<':
return LShift;
case '>':
Expand Down
20 changes: 20 additions & 0 deletions py3k/Python/ceval.c
Expand Up @@ -1456,6 +1456,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
if (x != NULL) DISPATCH();
break;

TARGET(BINARY_AT)
w = POP();
v = TOP();
x = PyUnicode_FormatPrime(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
if (x != NULL) DISPATCH();
break;

TARGET(BINARY_ADD)
w = POP();
v = TOP();
Expand Down Expand Up @@ -1617,6 +1627,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
if (x != NULL) DISPATCH();
break;

TARGET(INPLACE_AT)
w = POP();
v = TOP();
x = PyUnicode_FormatPrime(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
if (x != NULL) DISPATCH();
break;

TARGET(INPLACE_ADD)
w = POP();
v = TOP();
Expand Down
6 changes: 6 additions & 0 deletions py3k/Python/compile.c
Expand Up @@ -716,6 +716,7 @@ opcode_stack_effect(int opcode, int oparg)
case BINARY_POWER:
case BINARY_MULTIPLY:
case BINARY_MODULO:
case BINARY_AT:
case BINARY_ADD:
case BINARY_SUBTRACT:
case BINARY_SUBSCR:
Expand All @@ -730,6 +731,7 @@ opcode_stack_effect(int opcode, int oparg)
case INPLACE_SUBTRACT:
case INPLACE_MULTIPLY:
case INPLACE_MODULO:
case INPLACE_AT:
return -1;
case STORE_SUBSCR:
return -3;
Expand Down Expand Up @@ -2388,6 +2390,8 @@ binop(struct compiler *c, operator_ty op)
return BINARY_TRUE_DIVIDE;
case Mod:
return BINARY_MODULO;
case At:
return BINARY_AT;
case Pow:
return BINARY_POWER;
case LShift:
Expand Down Expand Up @@ -2452,6 +2456,8 @@ inplace_binop(struct compiler *c, operator_ty op)
return INPLACE_TRUE_DIVIDE;
case Mod:
return INPLACE_MODULO;
case At:
return INPLACE_AT;
case Pow:
return INPLACE_POWER;
case LShift:
Expand Down
4 changes: 2 additions & 2 deletions py3k/Python/opcode_targets.h
Expand Up @@ -29,8 +29,8 @@ static void *opcode_targets[256] = {
&&TARGET_BINARY_TRUE_DIVIDE,
&&TARGET_INPLACE_FLOOR_DIVIDE,
&&TARGET_INPLACE_TRUE_DIVIDE,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_BINARY_AT,
&&TARGET_INPLACE_AT,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
Expand Down

0 comments on commit 5c8bdf7

Please sign in to comment.