Commit dc4b93db authored by Guido van Rossum's avatar Guido van Rossum

* listobject.c (list_ass_slice): XDECREF instead of DECREF so

  setlistslice() can be used to cut the unused part out of a freshly made
  slice (as done by bagof()).  [needed by the next mod!]
* structural changes to bagof(), map() etc.
parent 4bd023f8
...@@ -401,9 +401,9 @@ list_ass_slice(a, ilow, ihigh, v) ...@@ -401,9 +401,9 @@ list_ass_slice(a, ilow, ihigh, v)
ihigh = a->ob_size; ihigh = a->ob_size;
item = a->ob_item; item = a->ob_item;
d = n - (ihigh-ilow); d = n - (ihigh-ilow);
if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */ if (d <= 0) { /* Delete -d items; XDECREF ihigh-ilow items */
for (k = ilow; k < ihigh; k++) for (k = ilow; k < ihigh; k++)
DECREF(item[k]); XDECREF(item[k]);
if (d < 0) { if (d < 0) {
for (/*k = ihigh*/; k < a->ob_size; k++) for (/*k = ihigh*/; k < a->ob_size; k++)
item[k+d] = item[k]; item[k+d] = item[k];
...@@ -412,7 +412,7 @@ list_ass_slice(a, ilow, ihigh, v) ...@@ -412,7 +412,7 @@ list_ass_slice(a, ilow, ihigh, v)
a->ob_item = item; a->ob_item = item;
} }
} }
else { /* Insert d items; DECREF ihigh-ilow items */ else { /* Insert d items; XDECREF ihigh-ilow items */
RESIZE(item, object *, a->ob_size + d); RESIZE(item, object *, a->ob_size + d);
if (item == NULL) { if (item == NULL) {
err_nomem(); err_nomem();
...@@ -421,13 +421,13 @@ list_ass_slice(a, ilow, ihigh, v) ...@@ -421,13 +421,13 @@ list_ass_slice(a, ilow, ihigh, v)
for (k = a->ob_size; --k >= ihigh; ) for (k = a->ob_size; --k >= ihigh; )
item[k+d] = item[k]; item[k+d] = item[k];
for (/*k = ihigh-1*/; k >= ilow; --k) for (/*k = ihigh-1*/; k >= ilow; --k)
DECREF(item[k]); XDECREF(item[k]);
a->ob_item = item; a->ob_item = item;
a->ob_size += d; a->ob_size += d;
} }
for (k = 0; k < n; k++, ilow++) { for (k = 0; k < n; k++, ilow++) {
object *w = b->ob_item[k]; object *w = b->ob_item[k];
INCREF(w); XINCREF(w);
item[ilow] = w; item[ilow] = w;
} }
return 0; return 0;
......
...@@ -71,55 +71,37 @@ builtin_bagof(self, args) ...@@ -71,55 +71,37 @@ builtin_bagof(self, args)
object *self; object *self;
object *args; object *args;
{ {
object *func, *seq, *arg, *result; object *func, *seq, *result;
sequence_methods *sqf; sequence_methods *sqf;
int len, newfunc = 0; int len;
register int i,j; register int i, j;
static char bagof_err[] = "bagof() requires 1 or 2 args";
if (args == NULL) { if (!getargs(args, "(OO)", &func, &seq))
err_setstr(TypeError, bagof_err);
return NULL; return NULL;
}
if (is_tupleobject(args)) { if (is_stringobject(func)) {
if (gettuplesize(args) != 2) { if ((func = exec_eval(func, lambda_input)) == NULL)
err_setstr(TypeError, bagof_err);
return NULL; return NULL;
}
func = gettupleitem(args, 0);
seq = gettupleitem(args, 1);
if (is_stringobject(func)) {
if ((func = exec_eval(func, lambda_input)) == NULL)
return NULL;
newfunc = 1;
}
} }
else { else {
func = None; INCREF(func);
seq = args;
} }
/* check for special cases; strings and tuples are returned as same */
if (is_stringobject(seq)) { if (is_stringobject(seq)) {
object *r = filterstring(func, seq); object *r = filterstring(func, seq);
if (newfunc) DECREF(func);
DECREF(func);
return r; return r;
} }
else if (is_tupleobject(seq)) { if (is_tupleobject(seq)) {
object *r = filtertuple(func, seq); object *r = filtertuple(func, seq);
if (newfunc) DECREF(func);
DECREF(func);
return r; return r;
} }
if (! (sqf = seq->ob_type->tp_as_sequence)) { if ((sqf = seq->ob_type->tp_as_sequence) == NULL) {
err_setstr(TypeError, err_setstr(TypeError,
"argument to bagof() must be a sequence type"); "argument 2 to bagof() must be a sequence type");
goto Fail_2; goto Fail_2;
} }
...@@ -130,65 +112,51 @@ builtin_bagof(self, args) ...@@ -130,65 +112,51 @@ builtin_bagof(self, args)
INCREF(seq); INCREF(seq);
result = seq; result = seq;
} }
else else {
if ((result = newlistobject(len)) == NULL) if ((result = newlistobject(len)) == NULL)
goto Fail_2; goto Fail_2;
}
if ((arg = newtupleobject(1)) == NULL)
goto Fail_1;
for (i = j = 0; i < len; ++i) { for (i = j = 0; i < len; ++i) {
object *ele, *value; object *item, *good;
int ok;
if (arg->ob_refcnt > 1) {
DECREF(arg);
if ((arg = newtupleobject(1)) == NULL)
goto Fail_1;
}
if ((ele = (*sqf->sq_item)(seq, i)) == NULL) if ((item = (*sqf->sq_item)(seq, i)) == NULL)
goto Fail_0; goto Fail_1;
if (func == None) if (func == None) {
value = ele; good = item;
}
else { else {
if (settupleitem(arg, 0, ele) < 0) object *arg = mkvalue("(O)", item);
goto Fail_0; DECREF(item);
if (arg == NULL)
if ((value = call_object(func, arg)) == NULL) goto Fail_1;
goto Fail_0; good = call_object(func, arg);
DECREF(arg);
if (good == NULL)
goto Fail_1;
} }
ok = testbool(good);
if (testbool(value)) { DECREF(good);
INCREF(ele); if (ok) {
if (setlistitem(result, j++, ele) < 0) INCREF(item);
goto Fail_0; if (setlistitem(result, j++, item) < 0)
goto Fail_1;
} }
DECREF(value);
} }
/* list_ass_slice() expects the rest of the list to be non-null */
for (i = j; i < len; ++i) {
INCREF(None);
if (setlistitem(result, i, None) < 0)
goto Fail_0;
}
DECREF(arg); if (setlistslice(result, j, len, NULL) < 0)
if (newfunc) goto Fail_1;
DECREF(func);
(*result->ob_type->tp_as_sequence->sq_ass_slice)(result, j, len, NULL); DECREF(func);
return result; return result;
Fail_0:
DECREF(arg);
Fail_1: Fail_1:
DECREF(result); DECREF(result);
Fail_2: Fail_2:
if (newfunc) DECREF(func);
DECREF(func);
return NULL; return NULL;
} }
...@@ -495,11 +463,15 @@ builtin_map(self, args) ...@@ -495,11 +463,15 @@ builtin_map(self, args)
if (is_stringobject(func)) { if (is_stringobject(func)) {
if ((func = exec_eval(func, lambda_input)) == NULL) if ((func = exec_eval(func, lambda_input)) == NULL)
return NULL; return NULL;
newfunc = 1; }
else {
INCREF(func);
} }
if ((seqs = (sequence *) malloc(n * sizeof(sequence))) == NULL) if ((seqs = NEW(sequence, n)) == NULL) {
return err_nomem(); err_nomem();
goto Fail_2;
}
for (len = -1, i = 0, sqp = seqs; i < n; ++i, ++sqp) { for (len = -1, i = 0, sqp = seqs; i < n; ++i, ++sqp) {
int curlen; int curlen;
...@@ -527,74 +499,64 @@ builtin_map(self, args) ...@@ -527,74 +499,64 @@ builtin_map(self, args)
if ((result = (object *) newlistobject(len)) == NULL) if ((result = (object *) newlistobject(len)) == NULL)
goto Fail_2; goto Fail_2;
if ((args = newtupleobject(n)) == NULL) /* XXX Special case map(None, single_list) could be more efficient */
goto Fail_1;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
object *arg, *value; object *arglist, *item;
if (args->ob_refcnt > 1) { if ((arglist = newtupleobject(n)) == NULL)
DECREF(args); goto Fail_1;
if ((args = newtupleobject(n)) == NULL)
goto Fail_1;
}
for (j = 0, sqp = seqs; j < n; ++j, ++sqp) { for (j = 0, sqp = seqs; j < n; ++j, ++sqp) {
if (i >= sqp->len) { if (i >= sqp->len) {
INCREF(None); INCREF(None);
if (settupleitem(args, j, None) < 0) item = None;
goto Fail_0;
arg = None;
} }
else { else {
if ((arg = (*sqp->sqf->sq_item)(sqp->seq, i)) == NULL) item = (*sqp->sqf->sq_item)(sqp->seq, i);
if (item == NULL)
goto Fail_0; goto Fail_0;
if (settupleitem(args, j, arg) < 0)
goto Fail_0;
} }
if (settupleitem(arglist, j, item) < 0)
goto Fail_0;
continue;
Fail_0:
DECREF(arglist);
goto Fail_1;
} }
if (func == None) { if (func == None) {
if (n == 1) { /* avoid creating singleton */ if (n == 1) { /* avoid creating singleton */
INCREF(arg); INCREF(item); /* This is arglist[0] !!! */
if (setlistitem(result, i, arg) < 0) DECREF(arglist);
goto Fail_0; if (setlistitem(result, i, item) < 0)
goto Fail_1;
} }
else { else {
INCREF(args); if (setlistitem(result, i, arglist) < 0)
if (setlistitem(result, i, args) < 0) goto Fail_1;
goto Fail_0;
} }
} }
else { else {
if ((value = call_object(func, args)) == NULL) object *value = call_object(func, arglist);
goto Fail_0; DECREF(arglist);
if (value == NULL)
goto Fail_1;
if (setlistitem((object *) result, i, value) < 0) if (setlistitem((object *) result, i, value) < 0)
goto Fail_0; goto Fail_1;
} }
} }
if (seqs) free(seqs); if (seqs) DEL(seqs);
DECREF(func);
DECREF(args);
if (newfunc)
DECREF(func);
return result; return result;
Fail_0:
DECREF(args);
Fail_1: Fail_1:
DECREF(result); DECREF(result);
Fail_2: Fail_2:
if (newfunc) DECREF(func);
DECREF(func); if (seqs) DEL(seqs);
if (seqs) free(seqs);
return NULL; return NULL;
} }
...@@ -990,7 +952,7 @@ builtin_reduce(self, args) ...@@ -990,7 +952,7 @@ builtin_reduce(self, args)
sequence_methods *sqf; sequence_methods *sqf;
static char reduce_err[] = "reduce() requires 2 or 3 args"; static char reduce_err[] = "reduce() requires 2 or 3 args";
register int i; register int i;
int start = 0, newfunc = 0; int start = 0;
int len; int len;
if (args == NULL || !is_tupleobject(args)) { if (args == NULL || !is_tupleobject(args)) {
...@@ -1018,7 +980,9 @@ builtin_reduce(self, args) ...@@ -1018,7 +980,9 @@ builtin_reduce(self, args)
if (is_stringobject(func)) { if (is_stringobject(func)) {
if ((func = exec_eval(func, lambda_input)) == NULL) if ((func = exec_eval(func, lambda_input)) == NULL)
return NULL; return NULL;
newfunc = 1; }
else {
INCREF(func);
} }
if ((len = (*sqf->sq_length)(seq)) < 0) if ((len = (*sqf->sq_length)(seq)) < 0)
...@@ -1061,20 +1025,17 @@ builtin_reduce(self, args) ...@@ -1061,20 +1025,17 @@ builtin_reduce(self, args)
} }
DECREF(args); DECREF(args);
if (newfunc) DECREF(func);
DECREF(func);
return result; return result;
/* XXX I hate goto's. I hate goto's. I hate goto's. I hate goto's. */
Fail_0: Fail_0:
DECREF(args); DECREF(args);
goto Fail_2; goto Fail_2;
Fail_1: Fail_1:
DECREF(result); DECREF(result);
Fail_2: Fail_2:
if (newfunc) DECREF(func);
DECREF(func);
return NULL; return NULL;
} }
...@@ -1310,14 +1271,14 @@ coerce(pv, pw) ...@@ -1310,14 +1271,14 @@ coerce(pv, pw)
} }
/* Filter a tuple through a function */ /* Helper for bagof(): filter a tuple through a function */
static object * static object *
filtertuple(func, tuple) filtertuple(func, tuple)
object *func; object *func;
object *tuple; object *tuple;
{ {
object *arg, *result; object *result;
register int i, j; register int i, j;
int len = gettuplesize(tuple), shared = 0; int len = gettuplesize(tuple), shared = 0;
...@@ -1330,42 +1291,34 @@ filtertuple(func, tuple) ...@@ -1330,42 +1291,34 @@ filtertuple(func, tuple)
if ((result = newtupleobject(len)) == NULL) if ((result = newtupleobject(len)) == NULL)
return NULL; return NULL;
if ((arg = newtupleobject(1)) == NULL)
goto Fail_1;
for (i = j = 0; i < len; ++i) { for (i = j = 0; i < len; ++i) {
object *ele, *value; object *item, *good;
int ok;
if (arg->ob_refcnt > 1) { if ((item = gettupleitem(tuple, i)) == NULL)
DECREF(arg); goto Fail_1;
if ((arg = newtupleobject(1)) == NULL) if (func == None) {
goto Fail_1; INCREF(item);
good = item;
} }
if ((ele = gettupleitem(tuple, i)) == NULL)
goto Fail_0;
INCREF(ele);
if (func == None)
value = ele;
else { else {
if (settupleitem(arg, 0, ele) < 0) object *arg = mkvalue("(O)", item);
goto Fail_0; if (arg == NULL)
goto Fail_1;
if ((value = call_object(func, arg)) == NULL) good = call_object(func, arg);
goto Fail_0; DECREF(arg);
if (good == NULL)
goto Fail_1;
} }
ok = testbool(good);
if (testbool(value)) { DECREF(good);
INCREF(ele); if (ok) {
if (settupleitem(result, j++, ele) < 0) INCREF(item);
goto Fail_0; if (settupleitem(result, j++, item) < 0)
goto Fail_1;
} }
DECREF(value);
} }
DECREF(arg);
if (resizetuple(&result, j) < 0) if (resizetuple(&result, j) < 0)
return NULL; return NULL;
...@@ -1374,8 +1327,6 @@ filtertuple(func, tuple) ...@@ -1374,8 +1327,6 @@ filtertuple(func, tuple)
return result; return result;
Fail_0:
DECREF(arg);
Fail_1: Fail_1:
if (!shared) if (!shared)
DECREF(result); DECREF(result);
...@@ -1383,14 +1334,14 @@ Fail_1: ...@@ -1383,14 +1334,14 @@ Fail_1:
} }
/* Filter a string through a function */ /* Helper for bagof(): filter a string through a function */
static object * static object *
filterstring(func, strobj) filterstring(func, strobj)
object *func; object *func;
object *strobj; object *strobj;
{ {
object *arg, *result; object *result;
register int i, j; register int i, j;
int len = getstringsize(strobj), shared = 0; int len = getstringsize(strobj), shared = 0;
...@@ -1415,36 +1366,28 @@ filterstring(func, strobj) ...@@ -1415,36 +1366,28 @@ filterstring(func, strobj)
} }
} }
if ((arg = newtupleobject(1)) == NULL)
goto Fail_1;
for (i = j = 0; i < len; ++i) { for (i = j = 0; i < len; ++i) {
object *ele, *value; object *item, *arg, *good;
int ok;
if (arg->ob_refcnt > 1) {
DECREF(arg); item = (*strobj->ob_type->tp_as_sequence->sq_item)(strobj, i);
if ((arg = newtupleobject(1)) == NULL) if (item == NULL)
goto Fail_1; goto Fail_1;
} arg = mkvalue("(O)", item);
DECREF(item);
if ((ele = (*strobj->ob_type->tp_as_sequence->sq_item) if (arg == NULL)
(strobj, i)) == NULL) goto Fail_1;
goto Fail_0; good = call_object(func, arg);
DECREF(arg);
if (settupleitem(arg, 0, ele) < 0) if (good == NULL)
goto Fail_0; goto Fail_1;
ok = testbool(good);
if ((value = call_object(func, arg)) == NULL) DECREF(good);
goto Fail_0; if (ok)
if (testbool(value))
GETSTRINGVALUE((stringobject *)result)[j++] = GETSTRINGVALUE((stringobject *)result)[j++] =
GETSTRINGVALUE((stringobject *)ele)[0]; GETSTRINGVALUE((stringobject *)item)[0];
DECREF(value);
} }
DECREF(arg);
if (resizestring(&result, j) < 0) if (resizestring(&result, j) < 0)
return NULL; return NULL;
...@@ -1453,8 +1396,6 @@ filterstring(func, strobj) ...@@ -1453,8 +1396,6 @@ filterstring(func, strobj)
return result; return result;
Fail_0:
DECREF(arg);
Fail_1: Fail_1:
if (!shared) if (!shared)
DECREF(result); DECREF(result);
......
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