summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2000-03-28 23:49:17 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2000-03-28 23:49:17 (GMT)
commit7690151c7e95f38b91a9c572ce29b4d8a4ca671d (patch)
treefb8eb51104f6aaa895c37c4c144072be016674f5 /Python
parent93a7c0fe6b2186448ebe35a5af0ac3880d8f16fc (diff)
downloadcpython-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.c279
-rw-r--r--Python/compile.c25
-rw-r--r--Python/graminit.c61
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"},
};