File: nestedscope.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (142 lines) | stat: -rw-r--r-- 4,673 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
135
136
137
138
139
140
141
142
from rpython.tool.uid import uid
from rpython.rlib import jit

from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import oefmt
from pypy.interpreter.mixedmodule import MixedModule


def make_cell_cmp(op):
    import operator
    cmp = getattr(operator, op)
    def descr_cell_(self, space, w_other):
        if not isinstance(w_other, Cell):
            return space.w_NotImplemented
        if self.w_value is None or w_other.w_value is None:
            return space.newbool(cmp(self._cmp_one_empty(w_other), 0))
        return getattr(space, op)(self.w_value, w_other.w_value)
    descr_cell_.func_name += op
    return descr_cell_


class Cell(W_Root):
    "A simple container for a wrapped value."

    _immutable_fields_ = ['family']

    def __init__(self, w_value, family):
        self.w_value = w_value
        self.family = family

    def get(self):
        if jit.isconstant(self):
            # ever_mutated is False if we never see a transition from not-None to
            # not-None. That means _elidable_get might return an out-of-date
            # None, and by now the cell was written to, with a not-None. So if
            # we see a None, we don't return that and instead read self.w_value
            # in the code below.
            if not self.family.ever_mutated:
                w_res = self._elidable_get()
                if w_res is not None:
                    return w_res
        if self.w_value is None:
            raise ValueError("get() from an empty cell")
        return self.w_value

    def empty(self):
        return self.w_value is None

    @jit.elidable
    def _elidable_get(self):
        return self.w_value

    def set(self, w_value):
        if not self.family.ever_mutated and self.w_value is not None:
            self.family.ever_mutated = True
        self.w_value = w_value

    def delete(self):
        if not self.family.ever_mutated:
            self.family.ever_mutated = True
        if self.w_value is None:
            raise ValueError("delete() on an empty cell")
        self.w_value = None

    def _cmp_one_empty(self, w_other):
        if self.w_value is None:
            if w_other.w_value is None:
                return 0
            return -1
        else:
            assert w_other.w_value is None
            return 1

    descr_eq = make_cell_cmp("eq")
    descr_ne = make_cell_cmp("ne")
    descr_lt = make_cell_cmp("lt")
    descr_gt = make_cell_cmp("gt")
    descr_ge = make_cell_cmp("ge")
    descr_le = make_cell_cmp("le")

    def descr__reduce__(self, space):
        w_mod = space.getbuiltinmodule('_pickle_support')
        mod = space.interp_w(MixedModule, w_mod)
        new_inst = mod.get('cell_new')
        if self.w_value is None:    # when would this happen?
            return space.newtuple2(new_inst, space.newtuple([]))
        tup = [self.w_value]
        return space.newtuple([new_inst, space.newtuple([]),
                               space.newtuple(tup)])

    def descr__setstate__(self, space, w_state):
        self.w_value = space.getitem(w_state, space.newint(0))

    def __repr__(self):
        """ representation for debugging purposes """
        if self.w_value is None:
            content = ""
        else:
            content = repr(self.w_value)
        return "<%s(%s) at 0x%x>" % (self.__class__.__name__,
                                     content, uid(self))

    def descr__repr__(self, space):
        if self.w_value is None:
            content = "empty"
        else:
            content = "%s object at 0x%s" % (space.type(self.w_value).name,
                                             self.w_value.getaddrstring(space))
        s = "<cell at 0x%s: %s>" % (self.getaddrstring(space), content)
        return space.newtext(s)

    def descr__cell_contents(self, space):
        try:
            return self.get()
        except ValueError:
            raise oefmt(space.w_ValueError, "Cell is empty")

    def descr_set_cell_contents(self, space, w_value):
        return self.set(w_value)

    def descr_del_cell_contents(self, space):
        try:
            return self.delete()
        except ValueError:
            pass # CPython ignores it


def descr_new_cell(space, w_type, w_obj=None):
    """ Create and return a new cell. If an argument is given, it is used as
    the cell_contents of the cell, otherwise the cell is empty. """
    return Cell(w_obj, DUMMY_FAMILY)


class CellFamily(object):
    _immutable_fields_ = ['ever_mutated?']

    def __init__(self, name):
        self.name = name
        self.ever_mutated = False

DUMMY_FAMILY = CellFamily("<dummy>")
DUMMY_FAMILY.ever_mutated = True