Kaydet (Commit) 12d12c5f authored tarafından Guido van Rossum's avatar Guido van Rossum

* compile.[ch]: support for lambda()

* PROTO.h, mymalloc.h: added #ifdefs for TURBOC and GNUC.
* allobjects.h: added #include "rangeobject.h"
* Grammar: added lambda_input; relaxed syntax for exec.
* bltinmodule.c: added bagof, map, reduce, lambda, xrange.
* tupleobject.[ch]: added resizetuple().
* rangeobject.[ch]: new object type to speed up range operations (not
  convinced this is needed!!!)
üst 444fc7c9
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
# Change log: # Change log:
# 25-Oct-93:
# Added lambda_input
# 18-Oct-93: # 18-Oct-93:
# Use testlist instead of exprlist in expr_stmt # Use testlist instead of exprlist in expr_stmt
# Add exec statement # Add exec statement
...@@ -75,13 +78,14 @@ ...@@ -75,13 +78,14 @@
# single_input is a single interactive statement; # single_input is a single interactive statement;
# file_input is a module or sequence of commands read from an input file; # file_input is a module or sequence of commands read from an input file;
# expr_input is the input for the input() function; # expr_input is the input for the input() function;
# eval_input is the input for the eval() function. # eval_input is the input for the eval() function;
# lambda_input is the input for the proposed lambda() function.
# NB: compound_stmt in single_input is followed by extra NEWLINE! # NB: compound_stmt in single_input is followed by extra NEWLINE!
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
file_input: (NEWLINE | stmt)* ENDMARKER file_input: (NEWLINE | stmt)* ENDMARKER
expr_input: testlist NEWLINE
eval_input: testlist NEWLINE* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER
lambda_input: varargslist ':' testlist NEWLINE* ENDMARKER
funcdef: 'def' NAME parameters ':' suite funcdef: 'def' NAME parameters ':' suite
parameters: '(' [varargslist] ')' parameters: '(' [varargslist] ')'
...@@ -108,7 +112,7 @@ access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)* ...@@ -108,7 +112,7 @@ access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)*
accesstype: NAME+ accesstype: NAME+
# accesstype should be ('public' | 'protected' | 'private') ['read'] ['write'] # accesstype should be ('public' | 'protected' | 'private') ['read'] ['write']
# but can't be because that would create undesirable reserved words! # but can't be because that would create undesirable reserved words!
exec_stmt: 'exec' expr ['in' expr [',' expr]] exec_stmt: 'exec' expr ['in' test [',' test]]
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
......
...@@ -46,6 +46,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -46,6 +46,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "intobject.h" #include "intobject.h"
#include "longobject.h" #include "longobject.h"
#include "floatobject.h" #include "floatobject.h"
#include "rangeobject.h"
#include "stringobject.h" #include "stringobject.h"
#include "tupleobject.h" #include "tupleobject.h"
#include "listobject.h" #include "listobject.h"
......
...@@ -54,10 +54,12 @@ extern typeobject Codetype; ...@@ -54,10 +54,12 @@ extern typeobject Codetype;
/* Public interface */ /* Public interface */
struct _node; /* Declare the existence of this type */ struct _node; /* Declare the existence of this type */
codeobject *compile PROTO((struct _node *, char *)); codeobject *_compile PROTO((struct _node *, char *, int));
codeobject *newcodeobject codeobject *newcodeobject
PROTO((object *, object *, object *, object *, object *)); PROTO((object *, object *, object *, object *, object *));
#define compile(n,f) (_compile((n),(f),0))
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
#define single_input 256 #define single_input 256
#define file_input 257 #define file_input 257
#define expr_input 258 #define eval_input 258
#define eval_input 259 #define lambda_input 259
#define funcdef 260 #define funcdef 260
#define parameters 261 #define parameters 261
#define varargslist 262 #define varargslist 262
......
...@@ -51,6 +51,16 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -51,6 +51,16 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define HAVE_STDLIB #define HAVE_STDLIB
#endif #endif
#ifdef __TURBOC__
#define ANY void
#define HAVE_STDLIB
#endif
#ifdef __GNUC__
#define ANY void
#define HAVE_STDLIB
#endif
#ifndef ANY #ifndef ANY
#define ANY char #define ANY char
#endif #endif
......
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
/* Range object interface */
/*
123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
rangeobject represents an integer range. This is an immutable object;
a range cannot change its value after creation.
Range objects behave like the corresponding tuple objects except that
they are represented by a start, stop, and step datamembers.
*/
extern typeobject Rangetype;
#define is_rangeobject(op) ((op)->ob_type == &Rangetype)
extern object *newrangeobject PROTO((long, long, long, int));
...@@ -58,6 +58,7 @@ extern int gettuplesize PROTO((object *)); ...@@ -58,6 +58,7 @@ extern int gettuplesize PROTO((object *));
extern object *gettupleitem PROTO((object *, int)); extern object *gettupleitem PROTO((object *, int));
extern int settupleitem PROTO((object *, int, object *)); extern int settupleitem PROTO((object *, int, object *));
extern object *gettupleslice PROTO((object *, int, int)); extern object *gettupleslice PROTO((object *, int, int));
extern int resizetuple PROTO((object **, int));
/* Macro, trading safety for speed */ /* Macro, trading safety for speed */
#define GETTUPLEITEM(op, i) ((op)->ob_item[i]) #define GETTUPLEITEM(op, i) ((op)->ob_item[i])
......
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
/* Range object implementation */
#include "allobjects.h"
typedef struct {
OB_HEAD
long start;
long step;
long len;
int reps;
} rangeobject;
object *
newrangeobject(start, len, step, reps)
long start, len, step;
int reps;
{
rangeobject *obj = (rangeobject *) newobject(&Rangetype);
obj->start = start;
obj->len = len;
obj->step = step;
obj->reps = reps;
return (object *) obj;
}
static void
range_dealloc(r)
rangeobject *r;
{
DEL(r);
}
static object *
range_item(r, i)
rangeobject *r;
int i;
{
if (i < 0 || i >= r->len * r->reps) {
err_setstr(IndexError, "range object index out of range");
return NULL;
}
return newintobject(r->start + (i % r->len) * r->step);
}
static int
range_length(r)
rangeobject *r;
{
return r->len * r->reps;
}
static object *
range_repr(r)
rangeobject *r;
{
char buf[80];
if (r->reps != 1)
sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
r->start,
r->start + r->len * r->step,
r->step,
r->reps);
else
sprintf(buf, "xrange(%ld, %ld, %ld)",
r->start,
r->start + r->len * r->step,
r->step);
return newstringobject(buf);
}
object *
range_concat(r, obj)
rangeobject *r;
object *obj;
{
if (is_rangeobject(obj)) {
rangeobject *s = (rangeobject *)obj;
if (r->start == s->start && r->len == s->len &&
r->step == s->step)
return newrangeobject(r->start, r->len, r->step,
r->reps + s->reps);
}
err_setstr(TypeError, "cannot concatenate different range objects");
return NULL;
}
object *
range_repeat(r, n)
rangeobject *r;
int n;
{
if (n < 0)
return (object *) newrangeobject(0, 0, 1, 1);
else if (n == 1) {
INCREF(r);
return (object *) r;
}
else
return (object *) newrangeobject(
r->start,
r->len,
r->step,
r->reps * n);
}
static int
range_compare(r1, r2)
rangeobject *r1, *r2;
{
if (r1->start != r2->start)
return r1->start - r2->start;
else if (r1->step != r2->step)
return r1->step - r2->step;
else if (r1->len != r2->len)
return r1->len - r2->len;
else
return r1->reps - r2->reps;
}
static object *
range_slice(r, low, high)
rangeobject *r;
int low, high;
{
if (r->reps != 1) {
err_setstr(TypeError, "cannot slice a replicated range");
return NULL;
}
if (low < 0)
low = 0;
else if (low > r->len)
low = r->len;
if (high < 0)
high = 0;
if (high < low)
high = low;
else if (high > r->len)
high = r->len;
return (object *) newrangeobject(
low * r->step + r->start,
high - low,
r->step,
1);
}
static sequence_methods range_as_sequence = {
range_length, /*sq_length*/
range_concat, /*sq_concat*/
range_repeat, /*sq_repeat*/
range_item, /*sq_item*/
range_slice, /*sq_slice*/
0, /*sq_ass_item*/
0, /*sq_ass_slice*/
};
typeobject Rangetype = {
OB_HEAD_INIT(&Typetype)
0, /* Number of items for varobject */
"range", /* Name of this type */
sizeof(rangeobject), /* Basic object size */
0, /* Item size for varobject */
range_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
range_compare, /*tp_compare*/
range_repr, /*tp_repr*/
0, /*tp_as_number*/
&range_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
};
...@@ -123,21 +123,18 @@ settupleitem(op, i, newitem) ...@@ -123,21 +123,18 @@ settupleitem(op, i, newitem)
{ {
register object *olditem; register object *olditem;
if (!is_tupleobject(op)) { if (!is_tupleobject(op)) {
if (newitem != NULL) XDECREF(newitem);
DECREF(newitem);
err_badcall(); err_badcall();
return -1; return -1;
} }
if (i < 0 || i >= ((tupleobject *)op) -> ob_size) { if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
if (newitem != NULL) XDECREF(newitem);
DECREF(newitem);
err_setstr(IndexError, "tuple assignment index out of range"); err_setstr(IndexError, "tuple assignment index out of range");
return -1; return -1;
} }
olditem = ((tupleobject *)op) -> ob_item[i]; olditem = ((tupleobject *)op) -> ob_item[i];
((tupleobject *)op) -> ob_item[i] = newitem; ((tupleobject *)op) -> ob_item[i] = newitem;
if (olditem != NULL) XDECREF(olditem);
DECREF(olditem);
return 0; return 0;
} }
...@@ -148,10 +145,8 @@ tupledealloc(op) ...@@ -148,10 +145,8 @@ tupledealloc(op)
register tupleobject *op; register tupleobject *op;
{ {
register int i; register int i;
for (i = 0; i < op->ob_size; i++) { for (i = 0; i < op->ob_size; i++)
if (op->ob_item[i] != NULL) XDECREF(op->ob_item[i]);
DECREF(op->ob_item[i]);
}
#if MAXSAVESIZE > 0 #if MAXSAVESIZE > 0
if (0 < op->ob_size && op->ob_size < MAXSAVESIZE) { if (0 < op->ob_size && op->ob_size < MAXSAVESIZE) {
op->ob_item[0] = (object *) free_list[op->ob_size]; op->ob_item[0] = (object *) free_list[op->ob_size];
...@@ -194,8 +189,7 @@ tuplerepr(v) ...@@ -194,8 +189,7 @@ tuplerepr(v)
joinstring(&s, comma); joinstring(&s, comma);
t = reprobject(v->ob_item[i]); t = reprobject(v->ob_item[i]);
joinstring(&s, t); joinstring(&s, t);
if (t != NULL) XDECREF(t);
DECREF(t);
} }
DECREF(comma); DECREF(comma);
if (v->ob_size == 1) { if (v->ob_size == 1) {
...@@ -397,3 +391,42 @@ typeobject Tupletype = { ...@@ -397,3 +391,42 @@ typeobject Tupletype = {
0, /*tp_as_mapping*/ 0, /*tp_as_mapping*/
tuplehash, /*tp_hash*/ tuplehash, /*tp_hash*/
}; };
/* The following function breaks the notion that tuples are immutable:
it changes the size of a tuple. We get away with this only if there
is only one module referencing the object. You can also think of it
as creating a new tuple object and destroying the old one, only
more efficiently. In any case, don't use this if the tuple may
already be known to some other part of the code... */
int
resizetuple(pv, newsize)
object **pv;
int newsize;
{
register object *v;
register tupleobject *sv;
v = *pv;
if (!is_tupleobject(v) || v->ob_refcnt != 1) {
*pv = 0;
DECREF(v);
err_badcall();
return -1;
}
/* XXX UNREF/NEWREF interface should be more symmetrical */
#ifdef REF_DEBUG
--ref_total;
#endif
UNREF(v);
*pv = (object *)
realloc((char *)v,
sizeof(tupleobject) + newsize * sizeof(object *));
if (*pv == NULL) {
DEL(v);
err_nomem();
return -1;
}
NEWREF(*pv);
((tupleobject *) *pv)->ob_size = newsize;
return 0;
}
This diff is collapsed.
...@@ -164,6 +164,7 @@ struct compiling { ...@@ -164,6 +164,7 @@ struct compiling {
int c_nexti; /* index into c_code */ int c_nexti; /* index into c_code */
int c_errors; /* counts errors occurred */ int c_errors; /* counts errors occurred */
int c_infunction; /* set when compiling a function */ int c_infunction; /* set when compiling a function */
int c_inlambda; /* set when compiling an expression */
int c_loops; /* counts nested loops */ int c_loops; /* counts nested loops */
int c_begin; /* begin of current loop, for 'continue' */ int c_begin; /* begin of current loop, for 'continue' */
int c_block[MAXBLOCKS]; /* stack of block types */ int c_block[MAXBLOCKS]; /* stack of block types */
...@@ -205,7 +206,7 @@ block_pop(c, type) ...@@ -205,7 +206,7 @@ block_pop(c, type)
/* Prototypes */ /* Prototypes */
static int com_init PROTO((struct compiling *, char *)); static int com_init PROTO((struct compiling *, char *, int));
static void com_free PROTO((struct compiling *)); static void com_free PROTO((struct compiling *));
static void com_done PROTO((struct compiling *)); static void com_done PROTO((struct compiling *));
static void com_node PROTO((struct compiling *, struct _node *)); static void com_node PROTO((struct compiling *, struct _node *));
...@@ -221,9 +222,10 @@ static void com_addopname PROTO((struct compiling *, int, node *)); ...@@ -221,9 +222,10 @@ static void com_addopname PROTO((struct compiling *, int, node *));
static void com_list PROTO((struct compiling *, node *, int)); static void com_list PROTO((struct compiling *, node *, int));
static int static int
com_init(c, filename) com_init(c, filename, inlambda)
struct compiling *c; struct compiling *c;
char *filename; char *filename;
int inlambda;
{ {
if ((c->c_code = newsizedstringobject((char *)NULL, 1000)) == NULL) if ((c->c_code = newsizedstringobject((char *)NULL, 1000)) == NULL)
goto fail_3; goto fail_3;
...@@ -236,6 +238,7 @@ com_init(c, filename) ...@@ -236,6 +238,7 @@ com_init(c, filename)
c->c_nexti = 0; c->c_nexti = 0;
c->c_errors = 0; c->c_errors = 0;
c->c_infunction = 0; c->c_infunction = 0;
c->c_inlambda = inlambda;
c->c_loops = 0; c->c_loops = 0;
c->c_begin = 0; c->c_begin = 0;
c->c_nblocks = 0; c->c_nblocks = 0;
...@@ -1792,7 +1795,7 @@ com_funcdef(c, n) ...@@ -1792,7 +1795,7 @@ com_funcdef(c, n)
{ {
object *v; object *v;
REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */ REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */
v = (object *)compile(n, c->c_filename); v = (object *)_compile(n, c->c_filename, 0);
if (v == NULL) if (v == NULL)
c->c_errors++; c->c_errors++;
else { else {
...@@ -1804,6 +1807,25 @@ com_funcdef(c, n) ...@@ -1804,6 +1807,25 @@ com_funcdef(c, n)
} }
} }
static void
com_lambda(c, n)
struct compiling *c;
node *n;
{
object *v;
REQ(n, lambda_input);
v = (object *)_compile(n, c->c_filename, 1);
if (v == NULL)
c->c_errors++;
else {
int i = com_addconst(c, v);
DECREF(v);
com_addoparg(c, LOAD_CONST, i);
com_addbyte(c, BUILD_FUNCTION);
com_addbyte(c, RETURN_VALUE);
}
}
static void static void
com_bases(c, n) com_bases(c, n)
struct compiling *c; struct compiling *c;
...@@ -1839,7 +1861,7 @@ com_classdef(c, n) ...@@ -1839,7 +1861,7 @@ com_classdef(c, n)
com_addoparg(c, BUILD_TUPLE, 0); com_addoparg(c, BUILD_TUPLE, 0);
else else
com_bases(c, CHILD(n, 3)); com_bases(c, CHILD(n, 3));
v = (object *)compile(n, c->c_filename); v = (object *)_compile(n, c->c_filename, 0);
if (v == NULL) if (v == NULL)
c->c_errors++; c->c_errors++;
else { else {
...@@ -2096,6 +2118,17 @@ compile_funcdef(c, n) ...@@ -2096,6 +2118,17 @@ compile_funcdef(c, n)
com_addbyte(c, RETURN_VALUE); com_addbyte(c, RETURN_VALUE);
} }
static void
compile_lambda(c, n)
struct compiling *c;
node *n;
{
REQ(n, lambda_input)
com_arglist(c, CHILD(n, 0));
com_node(c, CHILD(n, 2));
com_addbyte(c, RETURN_VALUE);
}
static void static void
compile_node(c, n) compile_node(c, n)
struct compiling *c; struct compiling *c;
...@@ -2120,12 +2153,11 @@ compile_node(c, n) ...@@ -2120,12 +2153,11 @@ compile_node(c, n)
com_addbyte(c, RETURN_VALUE); com_addbyte(c, RETURN_VALUE);
break; break;
case expr_input: /* Built-in function eval() */ case lambda_input: /* Built-in function lambda() */
com_node(c, CHILD(n, 0)); (c->c_inlambda ? compile_lambda : com_lambda)(c, n);
com_addbyte(c, RETURN_VALUE);
break; break;
case eval_input: /* Built-in function input() */ case eval_input: /* Built-in functions eval() and input() */
com_node(c, CHILD(n, 0)); com_node(c, CHILD(n, 0));
com_addbyte(c, RETURN_VALUE); com_addbyte(c, RETURN_VALUE);
break; break;
...@@ -2285,13 +2317,14 @@ optimize(c) ...@@ -2285,13 +2317,14 @@ optimize(c)
} }
codeobject * codeobject *
compile(n, filename) _compile(n, filename, inlambda)
node *n; node *n;
char *filename; char *filename;
int inlambda;
{ {
struct compiling sc; struct compiling sc;
codeobject *co; codeobject *co;
if (!com_init(&sc, filename)) if (!com_init(&sc, filename, inlambda))
return NULL; return NULL;
compile_node(&sc, n); compile_node(&sc, n);
com_done(&sc); com_done(&sc);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment