[Python-checkins] CVS: python/dist/src/Python ceval.c,2.168,2.169 compile.c,2.100,2.101 graminit.c,2.22,2.23

Jeremy Hylton python-dev@python.org
Tue, 28 Mar 2000 18:49:20 -0500


Update of /projects/cvsroot/python/dist/src/Python
In directory goon.cnri.reston.va.us:/home/jhylton/python/src/Python

Modified Files:
	ceval.c compile.c graminit.c 
Log Message:
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


Index: ceval.c
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Python/ceval.c,v
retrieving revision 2.168
retrieving revision 2.169
diff -C2 -r2.168 -r2.169
*** ceval.c	2000/02/23 22:18:48	2.168
--- ceval.c	2000/03/28 23:49:16	2.169
***************
*** 500,504 ****
  					PyErr_Format(PyExc_TypeError,
  					 "unexpected keyword argument: %.400s",
! 					 PyString_AsString(keyword));
  					goto fail;
  				}
--- 500,504 ----
  					PyErr_Format(PyExc_TypeError,
  					 "unexpected keyword argument: %.400s",
! 					    PyString_AsString(keyword));
  					goto fail;
  				}
***************
*** 507,512 ****
  			else {
  				if (GETLOCAL(j) != NULL) {
! 					PyErr_SetString(PyExc_TypeError,
! 						"keyword parameter redefined");
  					goto fail;
  				}
--- 507,513 ----
  			else {
  				if (GETLOCAL(j) != NULL) {
! 					PyErr_Format(PyExc_TypeError, 
! 				     "keyword parameter redefined: %.400s",
! 					     PyString_AsString(keyword));
  					goto fail;
  				}
***************
*** 1549,1671 ****
  
  		case CALL_FUNCTION:
  		{
! 			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;
! 					}
! 				}
  			}
! 			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 {
! 				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;
! 					}
! 				}
! 				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;
  		}
  		
--- 1550,1713 ----
  
  		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 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 {
! 			    /* 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 {
! 			    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;
! 				}
! 			    }
! 			    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;
! 				}
! 				err = PyDict_SetItem(kwdict, key, value);
! 				Py_DECREF(key);
! 				Py_DECREF(value);
! 				if (err)
! 				    break;
! 			    }
! 			    if (err) {
! 				Py_DECREF(args);
! 				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;
  		}
  		
***************
*** 2688,2695 ****
  		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);
  			return -1;
  		}
--- 2730,2736 ----
  		x = PyDict_GetItem(w, name);
  		if (x == NULL) {
! 			PyErr_Format(PyExc_ImportError, 
! 				     "cannot import name %.230s",
! 				     PyString_AsString(name));
  			return -1;
  		}

Index: compile.c
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Python/compile.c,v
retrieving revision 2.100
retrieving revision 2.101
diff -C2 -r2.100 -r2.101
*** compile.c	2000/03/10 23:01:36	2.100
--- compile.c	2000/03/28 23:49:16	2.101
***************
*** 1186,1189 ****
--- 1186,1192 ----
  		int i, na, nk;
  		int lineno = n->n_lineno;
+ 		int star_flag = 0;
+ 		int starstar_flag = 0;
+ 		int opcode;
  		REQ(n, arglist);
  		na = 0;
***************
*** 1191,1194 ****
--- 1194,1200 ----
  		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;
***************
*** 1202,1211 ****
  		}
  		Py_XDECREF(keywords);
  		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);
  	}
  }
--- 1208,1232 ----
  		}
  		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");
  		}
! 		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);
  	}
  }

Index: graminit.c
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Python/graminit.c,v
retrieving revision 2.22
retrieving revision 2.23
diff -C2 -r2.22 -r2.23
*** graminit.c	1998/04/09 21:38:55	2.22
--- graminit.c	2000/03/28 23:49:17	2.23
***************
*** 99,105 ****
  	{0, 1},
  };
! static arc arcs_5_2[2] = {
  	{12, 6},
- 	{23, 3},
  };
  static arc arcs_5_3[1] = {
--- 99,104 ----
  	{0, 1},
  };
! static arc arcs_5_2[1] = {
  	{12, 6},
  };
  static arc arcs_5_3[1] = {
***************
*** 126,140 ****
  	{0, 8},
  };
! static arc arcs_5_9[2] = {
  	{24, 3},
- 	{23, 10},
  };
! static arc arcs_5_10[1] = {
! 	{23, 3},
! };
! static state states_5[11] = {
  	{3, arcs_5_0},
  	{3, arcs_5_1},
! 	{2, arcs_5_2},
  	{1, arcs_5_3},
  	{1, arcs_5_4},
--- 125,135 ----
  	{0, 8},
  };
! static arc arcs_5_9[1] = {
  	{24, 3},
  };
! static state states_5[10] = {
  	{3, arcs_5_0},
  	{3, arcs_5_1},
! 	{1, arcs_5_2},
  	{1, arcs_5_3},
  	{1, arcs_5_4},
***************
*** 143,148 ****
  	{1, arcs_5_7},
  	{2, arcs_5_8},
! 	{2, arcs_5_9},
! 	{1, arcs_5_10},
  };
  static arc arcs_6_0[2] = {
--- 138,142 ----
  	{1, arcs_5_7},
  	{2, arcs_5_8},
! 	{1, arcs_5_9},
  };
  static arc arcs_6_0[2] = {
***************
*** 1170,1188 ****
  	{1, arcs_54_7},
  };
! static arc arcs_55_0[1] = {
  	{123, 1},
  };
  static arc arcs_55_1[2] = {
! 	{22, 2},
  	{0, 1},
  };
! static arc arcs_55_2[2] = {
  	{123, 1},
! 	{0, 2},
  };
! static state states_55[3] = {
! 	{1, arcs_55_0},
  	{2, arcs_55_1},
! 	{2, arcs_55_2},
  };
  static arc arcs_56_0[1] = {
--- 1164,1207 ----
  	{1, arcs_54_7},
  };
! static arc arcs_55_0[3] = {
  	{123, 1},
+ 	{23, 2},
+ 	{24, 3},
  };
  static arc arcs_55_1[2] = {
! 	{22, 4},
  	{0, 1},
  };
! static arc arcs_55_2[1] = {
! 	{21, 5},
! };
! static arc arcs_55_3[1] = {
! 	{21, 6},
! };
! static arc arcs_55_4[4] = {
  	{123, 1},
! 	{23, 2},
! 	{24, 3},
! 	{0, 4},
! };
! static arc arcs_55_5[2] = {
! 	{22, 7},
! 	{0, 5},
  };
! 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},
! 	{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] = {
***************
*** 1216,1220 ****
  	{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,
  	 "\000\020\201\001\000\000\000\000\000\000\000\000\000\000\000\000"},
  	{262, "fpdef", 0, 4, states_6,
--- 1235,1239 ----
  	{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, 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,
***************
*** 1316,1321 ****
  	{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"},
  	{312, "argument", 0, 4, states_56,
  	 "\000\020\001\000\000\000\000\000\000\200\000\000\060\242\074\000"},
--- 1335,1340 ----
  	{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, 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"},