diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-03-28 23:49:17 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-03-28 23:49:17 (GMT) |
commit | 7690151c7e95f38b91a9c572ce29b4d8a4ca671d (patch) | |
tree | fb8eb51104f6aaa895c37c4c144072be016674f5 /Python | |
parent | 93a7c0fe6b2186448ebe35a5af0ac3880d8f16fc (diff) | |
download | cpython-7690151c7e95f38b91a9c572ce29b4d8a4ca671d.zip cpython-7690151c7e95f38b91a9c572ce29b4d8a4ca671d.tar.gz cpython-7690151c7e95f38b91a9c572ce29b4d8a4ca671d.tar.bz2 |
slightly modified version of Greg Ewing's extended call syntax patch
executive summary:
Instead of typing 'apply(f, args, kwargs)' you can type 'f(*arg, **kwargs)'.
Some file-by-file details follow.
Grammar/Grammar:
simplify varargslist, replacing '*' '*' with '**'
add * & ** options to arglist
Include/opcode.h & Lib/dis.py:
define three new opcodes
CALL_FUNCTION_VAR
CALL_FUNCTION_KW
CALL_FUNCTION_VAR_KW
Python/ceval.c:
extend TypeError "keyword parameter redefined" message to include
the name of the offending keyword
reindent CALL_FUNCTION using four spaces
add handling of sequences and dictionaries using extend calls
fix function import_from to use PyErr_Format
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 279 | ||||
-rw-r--r-- | Python/compile.c | 25 | ||||
-rw-r--r-- | Python/graminit.c | 61 |
3 files changed, 223 insertions, 142 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 46a60f1..7a97771 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -499,15 +499,16 @@ eval_code2(co, globals, locals, if (kwdict == NULL) { PyErr_Format(PyExc_TypeError, "unexpected keyword argument: %.400s", - PyString_AsString(keyword)); + PyString_AsString(keyword)); goto fail; } PyDict_SetItem(kwdict, keyword, value); } else { if (GETLOCAL(j) != NULL) { - PyErr_SetString(PyExc_TypeError, - "keyword parameter redefined"); + PyErr_Format(PyExc_TypeError, + "keyword parameter redefined: %.400s", + PyString_AsString(keyword)); goto fail; } Py_INCREF(value); @@ -1548,125 +1549,166 @@ eval_code2(co, globals, locals, break; case CALL_FUNCTION: + case CALL_FUNCTION_VAR: + case CALL_FUNCTION_KW: + case CALL_FUNCTION_VAR_KW: { - int na = oparg & 0xff; - int nk = (oparg>>8) & 0xff; - int n = na + 2*nk; - PyObject **pfunc = stack_pointer - n - 1; - PyObject *func = *pfunc; - PyObject *self = NULL; - PyObject *class = NULL; - f->f_lasti = INSTR_OFFSET() - 3; /* For tracing */ - if (PyMethod_Check(func)) { - self = PyMethod_Self(func); - class = PyMethod_Class(func); - func = PyMethod_Function(func); - Py_INCREF(func); - if (self != NULL) { - Py_INCREF(self); - Py_DECREF(*pfunc); - *pfunc = self; - na++; - n++; - } - else { - /* Unbound methods must be - called with an instance of - the class (or a derived - class) as first argument */ - if (na > 0 && - (self = stack_pointer[-n]) - != NULL && - PyInstance_Check(self) && - PyClass_IsSubclass( - (PyObject *) - (((PyInstanceObject *)self) - ->in_class), - class)) - /* Handy-dandy */ ; - else { - PyErr_SetString( - PyExc_TypeError, - "unbound method must be called with class instance 1st argument"); - x = NULL; - break; - } - } + int na = oparg & 0xff; + int nk = (oparg>>8) & 0xff; + int flags = (opcode - CALL_FUNCTION) & 3; + int n = na + 2*nk + (flags & 1) + ((flags >> 1) & 1); + PyObject **pfunc = stack_pointer - n - 1; + PyObject *func = *pfunc; + PyObject *self = NULL; + PyObject *class = NULL; + f->f_lasti = INSTR_OFFSET() - 3; /* For tracing */ + if (PyMethod_Check(func)) { + self = PyMethod_Self(func); + class = PyMethod_Class(func); + func = PyMethod_Function(func); + Py_INCREF(func); + if (self != NULL) { + Py_INCREF(self); + Py_DECREF(*pfunc); + *pfunc = self; + na++; + n++; } - else - Py_INCREF(func); - if (PyFunction_Check(func)) { - PyObject *co = PyFunction_GetCode(func); - PyObject *globals = - PyFunction_GetGlobals(func); - PyObject *argdefs = - PyFunction_GetDefaults(func); - PyObject **d; - int nd; - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = ((PyTupleObject *)argdefs) -> - ob_size; - } - else { - d = NULL; - nd = 0; - } - x = eval_code2( - (PyCodeObject *)co, - globals, (PyObject *)NULL, - stack_pointer-n, na, - stack_pointer-2*nk, nk, - d, nd, - class); + else { + /* Unbound methods must be called with an + instance of the class (or a derived + class) as first argument */ + if (na > 0 && (self = stack_pointer[-n]) != NULL + && PyInstance_Check(self) + && PyClass_IsSubclass((PyObject *) + (((PyInstanceObject *)self)->in_class), + class)) + /* Handy-dandy */ ; + else { + PyErr_SetString(PyExc_TypeError, + "unbound method must be called with class instance 1st argument"); + x = NULL; + break; + } + } + } + else + Py_INCREF(func); + if (PyFunction_Check(func) && flags == 0) { + PyObject *co = PyFunction_GetCode(func); + PyObject *globals = PyFunction_GetGlobals(func); + PyObject *argdefs = PyFunction_GetDefaults(func); + PyObject **d; + int nd; + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = ((PyTupleObject *)argdefs)->ob_size; } else { - PyObject *args = PyTuple_New(na); - PyObject *kwdict = NULL; - if (args == NULL) { - x = NULL; - break; - } - if (nk > 0) { - kwdict = PyDict_New(); - if (kwdict == NULL) { - x = NULL; - break; - } - err = 0; - while (--nk >= 0) { - PyObject *value = POP(); - PyObject *key = POP(); - err = PyDict_SetItem( - kwdict, key, value); - Py_DECREF(key); - Py_DECREF(value); - if (err) - break; - } - if (err) { - Py_DECREF(args); - Py_DECREF(kwdict); - break; - } + d = NULL; + nd = 0; + } + x = eval_code2((PyCodeObject *)co, globals, + (PyObject *)NULL, stack_pointer-n, na, + stack_pointer-2*nk, nk, d, nd, + class); + } + else { + int nstar = 0; + PyObject *args; + PyObject *stararg = 0; + PyObject *kwdict = NULL; + if (flags & 2) { + kwdict = POP(); + if (!PyDict_Check(kwdict)) { + PyErr_SetString(PyExc_TypeError, + "** argument must be a dictionary"); + x = NULL; + break; + } + } + if (flags & 1) { + stararg = POP(); + if (!PySequence_Check(stararg)) { + PyErr_SetString(PyExc_TypeError, + "* argument must be a sequence"); + x = NULL; + break; + } + nstar = PySequence_Length(stararg); + } + if (nk > 0) { + if (kwdict == NULL) { + kwdict = PyDict_New(); + if (kwdict == NULL) { + x = NULL; + break; } - while (--na >= 0) { - w = POP(); - PyTuple_SET_ITEM(args, na, w); + } + err = 0; + while (--nk >= 0) { + PyObject *value = POP(); + PyObject *key = POP(); + if (PyDict_GetItem(kwdict, key) != NULL) { + err = 1; + PyErr_Format(PyExc_TypeError, + "keyword parameter redefined: %.400s", + PyString_AsString(key)); + break; } - x = PyEval_CallObjectWithKeywords( - func, args, kwdict); + err = PyDict_SetItem(kwdict, key, value); + Py_DECREF(key); + Py_DECREF(value); + if (err) + break; + } + if (err) { Py_DECREF(args); - Py_XDECREF(kwdict); - } - Py_DECREF(func); - while (stack_pointer > pfunc) { - w = POP(); - Py_DECREF(w); - } - PUSH(x); - if (x != NULL) continue; - break; + Py_DECREF(kwdict); + break; + } + } + args = PyTuple_New(na + nstar); + if (args == NULL) { + x = NULL; + break; + } + if (stararg) { + PyObject *t = NULL; + int i; + if (!PyTuple_Check(stararg)) { + /* must be sequence to pass earlier test */ + t = PySequence_Tuple(stararg); + if (t == NULL) { + x = NULL; + break; + } + Py_DECREF(stararg); + stararg = t; + } + for (i = 0; i < nstar; i++) { + PyObject *a = PyTuple_GET_ITEM(stararg, i); + Py_INCREF(a); + PyTuple_SET_ITEM(args, na + i, a); + } + Py_DECREF(stararg); + } + while (--na >= 0) { + w = POP(); + PyTuple_SET_ITEM(args, na, w); + } + x = PyEval_CallObjectWithKeywords(func, args, kwdict); + Py_DECREF(args); + Py_XDECREF(kwdict); + } + Py_DECREF(func); + while (stack_pointer > pfunc) { + w = POP(); + Py_DECREF(w); + } + PUSH(x); + if (x != NULL) continue; + break; } case MAKE_FUNCTION: @@ -2687,10 +2729,9 @@ import_from(locals, v, name) else { x = PyDict_GetItem(w, name); if (x == NULL) { - char buf[250]; - sprintf(buf, "cannot import name %.230s", - PyString_AsString(name)); - PyErr_SetString(PyExc_ImportError, buf); + PyErr_Format(PyExc_ImportError, + "cannot import name %.230s", + PyString_AsString(name)); return -1; } else diff --git a/Python/compile.c b/Python/compile.c index 72848fa..1eed7c0 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1185,11 +1185,17 @@ com_call_function(c, n) PyObject *keywords = NULL; int i, na, nk; int lineno = n->n_lineno; + int star_flag = 0; + int starstar_flag = 0; + int opcode; REQ(n, arglist); na = 0; nk = 0; for (i = 0; i < NCH(n); i += 2) { node *ch = CHILD(n, i); + if (TYPE(ch) == STAR || + TYPE(ch) == DOUBLESTAR) + break; if (ch->n_lineno != lineno) { lineno = ch->n_lineno; com_addoparg(c, SET_LINENO, lineno); @@ -1201,12 +1207,27 @@ com_call_function(c, n) nk++; } Py_XDECREF(keywords); + while (i < NCH(n)) { + node *tok = CHILD(n, i); + node *ch = CHILD(n, i+1); + i += 3; + switch (TYPE(tok)) { + case STAR: star_flag = 1; break; + case DOUBLESTAR: starstar_flag = 1; break; + } + com_node(c, ch); + } if (na > 255 || nk > 255) { com_error(c, PyExc_SyntaxError, "more than 255 arguments"); } - com_addoparg(c, CALL_FUNCTION, na | (nk << 8)); - com_pop(c, na + 2*nk); + if (star_flag || starstar_flag) + opcode = CALL_FUNCTION_STAR - 1 + + star_flag + (starstar_flag << 1); + else + opcode = CALL_FUNCTION; + com_addoparg(c, opcode, na | (nk << 8)); + com_pop(c, na + 2*nk + star_flag + starstar_flag); } } diff --git a/Python/graminit.c b/Python/graminit.c index ba9359e..35d8de4 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -98,9 +98,8 @@ static arc arcs_5_1[3] = { {22, 5}, {0, 1}, }; -static arc arcs_5_2[2] = { +static arc arcs_5_2[1] = { {12, 6}, - {23, 3}, }; static arc arcs_5_3[1] = { {12, 7}, @@ -125,25 +124,20 @@ static arc arcs_5_8[2] = { {22, 5}, {0, 8}, }; -static arc arcs_5_9[2] = { +static arc arcs_5_9[1] = { {24, 3}, - {23, 10}, }; -static arc arcs_5_10[1] = { - {23, 3}, -}; -static state states_5[11] = { +static state states_5[10] = { {3, arcs_5_0}, {3, arcs_5_1}, - {2, arcs_5_2}, + {1, arcs_5_2}, {1, arcs_5_3}, {1, arcs_5_4}, {4, arcs_5_5}, {2, arcs_5_6}, {1, arcs_5_7}, {2, arcs_5_8}, - {2, arcs_5_9}, - {1, arcs_5_10}, + {1, arcs_5_9}, }; static arc arcs_6_0[2] = { {12, 1}, @@ -1169,21 +1163,46 @@ static state states_54[8] = { {1, arcs_54_6}, {1, arcs_54_7}, }; -static arc arcs_55_0[1] = { +static arc arcs_55_0[3] = { {123, 1}, + {23, 2}, + {24, 3}, }; static arc arcs_55_1[2] = { - {22, 2}, + {22, 4}, {0, 1}, }; -static arc arcs_55_2[2] = { +static arc arcs_55_2[1] = { + {21, 5}, +}; +static arc arcs_55_3[1] = { + {21, 6}, +}; +static arc arcs_55_4[4] = { {123, 1}, - {0, 2}, + {23, 2}, + {24, 3}, + {0, 4}, +}; +static arc arcs_55_5[2] = { + {22, 7}, + {0, 5}, }; -static state states_55[3] = { - {1, arcs_55_0}, +static arc arcs_55_6[1] = { + {0, 6}, +}; +static arc arcs_55_7[1] = { + {24, 3}, +}; +static state states_55[8] = { + {3, arcs_55_0}, {2, arcs_55_1}, - {2, arcs_55_2}, + {1, arcs_55_2}, + {1, arcs_55_3}, + {4, arcs_55_4}, + {2, arcs_55_5}, + {1, arcs_55_6}, + {1, arcs_55_7}, }; static arc arcs_56_0[1] = { {21, 1}, @@ -1215,7 +1234,7 @@ static dfa dfas[57] = { "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {260, "parameters", 0, 4, states_4, "\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {261, "varargslist", 0, 11, states_5, + {261, "varargslist", 0, 10, states_5, "\000\020\201\001\000\000\000\000\000\000\000\000\000\000\000\000"}, {262, "fpdef", 0, 4, states_6, "\000\020\001\000\000\000\000\000\000\000\000\000\000\000\000\000"}, @@ -1315,8 +1334,8 @@ static dfa dfas[57] = { "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"}, {310, "classdef", 0, 8, states_54, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, - {311, "arglist", 0, 3, states_55, - "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"}, + {311, "arglist", 0, 8, states_55, + "\000\020\201\001\000\000\000\000\000\200\000\000\060\242\074\000"}, {312, "argument", 0, 4, states_56, "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"}, }; |