File: piterobject.c

package info (click to toggle)
psyco 1.5.1-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 1,864 kB
  • ctags: 3,295
  • sloc: ansic: 24,491; python: 5,573; perl: 1,309; makefile: 166; sh: 1
file content (134 lines) | stat: -rw-r--r-- 3,628 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "piterobject.h"
#if HAVE_GENERATORS


DEFINEFN vinfo_t* PsycoSeqIter_NEW(PsycoObject* po, vinfo_t* seq)
{
	vinfo_t* zero;
	vinfo_t* result = vinfo_new(VirtualTime_New(&psyco_computed_seqiter));
	result->array = array_new(SEQITER_TOTAL);
	result->array->items[iOB_TYPE] =
		vinfo_new(CompileTime_New((long)(&PySeqIter_Type)));
	/* the iterator index is immediately run-time because it is
	   very likely to be unpromoted to run-time anyway */
	zero = psyco_vi_Zero();
	result->array->items[iSEQITER_IT_INDEX] = make_runtime_copy(po, zero);
	vinfo_decref(zero, po);
	/*result->array->items[SEQITER_IT_INDEX] =
		vinfo_new(CompileTime_New(0));*/
	result->array->items[iSEQITER_IT_SEQ] = seq;
	return result;
}


static vinfo_t* piter_getiter(PsycoObject* po, vinfo_t* v)
{
	vinfo_incref(v);
	return v;
}

static vinfo_t* piter_next(PsycoObject* po, vinfo_t* v)
{
	vinfo_t* seq;
	vinfo_t* index;
	vinfo_t* result;
	
	seq = psyco_get_const(po, v, SEQITER_it_seq);
	if (seq == NULL)
		return NULL;

	index = psyco_get_field(po, v, SEQITER_it_index);
	if (index == NULL)
		return NULL;

	result = PsycoSequence_GetItem(po, seq, index);
	if (result == NULL) {
		vinfo_t* matches = PycException_Matches(po, PyExc_IndexError);
		if (runtime_NON_NULL_t(po, matches) == true) {
			PycException_SetVInfo(po, PyExc_StopIteration,
					      psyco_vi_None());
		}
	}
	else {
		/* very remotely potential incompatibility: when exhausted,
		   the internal iterator index is not incremented. Python
		   is not consistent in this respect. This could be an
		   issue if an iterator of a mutable object is not
		   immediately deleted when exhausted. Well, I guess that
		   muting an object we iterate over is generally considered
		   as DDIWWY (Don't Do It -- We Warned You.) */
		vinfo_t* index_plus_1 = integer_add_i(po, index, 1, true);
		if (index_plus_1 == NULL ||
		    !psyco_put_field(po, v, SEQITER_it_index, index_plus_1)) {
			vinfo_decref(result, po);
			result = NULL;
		}
		vinfo_xdecref(index_plus_1, po);
	}
	vinfo_decref(index, po);
	return result;
}


static bool compute_seqiter(PsycoObject* po, vinfo_t* v)
{
	vinfo_t* seq;
	vinfo_t* index;
	vinfo_t* newobj;

	index = vinfo_getitem(v, iSEQITER_IT_INDEX);
	if (index == NULL)
		return false;

	seq = vinfo_getitem(v, iSEQITER_IT_SEQ);
	if (seq == NULL)
		return false;

	newobj = psyco_generic_call(po, PySeqIter_New,
				    CfReturnRef|CfPyErrIfNull, "v", seq);
	if (newobj == NULL)
		return false;

	/* Put the current index into the seq iterator.
	   This is done by putting the value directly in the
	   seqiterobject structure; it could be done by calling
	   PyIter_Next() n times but obviously that's not too
	   good a solution */
	if (!psyco_knowntobe(index, 0)) {
		if (!psyco_put_field(po, v, SEQITER_it_index, index)) {
			vinfo_decref(newobj, po);
			return false;
		}
	}

	/* Remove the SEQITER_IT_INDEX entry from v->array because it
	   is a mutable field now, and could be changed at any time by
	   anybody .*/
	psyco_forget_field(po, v, SEQITER_it_index);

	vinfo_move(po, v, newobj);
	return true;
}

DEFINEVAR source_virtual_t psyco_computed_seqiter;


INITIALIZATIONFN
void psy_iterobject_init(void)
{
        Psyco_DefineMeta(PySeqIter_Type.tp_iter, &piter_getiter);
        Psyco_DefineMeta(PySeqIter_Type.tp_iternext, &piter_next);

        /* iterator object are mutable;
           they must be forced out of virtual-time across function calls */
        INIT_SVIRTUAL_NOCALL(psyco_computed_seqiter, compute_seqiter, 1);
}

#else /* !HAVE_GENERATORS */

INITIALIZATIONFN
void psy_iterobject_init(void)
{
}

#endif /* HAVE_GENERATORS */