~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/translator/c/support.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from pypy.rpython.lltypesystem import lltype
 
2
from pypy.translator.gensupp import NameManager
 
3
 
 
4
#
 
5
# use __slots__ declarations for node classes etc
 
6
# possible to turn it off while refactoring, experimenting
 
7
#
 
8
USESLOTS = True
 
9
 
 
10
PyObjPtr = lltype.Ptr(lltype.PyObject)
 
11
 
 
12
 
 
13
class ErrorValue:
 
14
    def __init__(self, TYPE):
 
15
        self.TYPE = TYPE
 
16
 
 
17
 
 
18
#
 
19
# helpers
 
20
#
 
21
def cdecl(ctype, cname, is_thread_local=False):
 
22
    """
 
23
    Produce a C declaration from a 'type template' and an identifier.
 
24
    The type template must contain a '@' sign at the place where the
 
25
    name should be inserted, according to the strange C syntax rules.
 
26
    """
 
27
    # the (@) case is for functions, where if there is a plain (@) around
 
28
    # the function name, we don't need the very confusing parenthesis
 
29
    __thread = ""
 
30
    if is_thread_local:
 
31
        __thread = "__thread "
 
32
    return __thread + ctype.replace('(@)', '@').replace('@', cname).strip()
 
33
 
 
34
def forward_cdecl(ctype, cname, standalone, is_thread_local=False):
 
35
    __thread = ""
 
36
    if is_thread_local:
 
37
        __thread = "__thread "
 
38
 
 
39
    cdecl_str = __thread + cdecl(ctype, cname)
 
40
    if standalone:
 
41
        return 'extern ' + cdecl_str
 
42
    else:
 
43
        return cdecl_str
 
44
    
 
45
def somelettersfrom(s):
 
46
    upcase = [c for c in s if c.isupper()]
 
47
    if not upcase:
 
48
        upcase = [c for c in s.title() if c.isupper()]
 
49
    locase = [c for c in s if c.islower()]
 
50
    if locase and upcase:
 
51
        return ''.join(upcase).lower()
 
52
    else:
 
53
        return s[:2].lower()
 
54
 
 
55
 
 
56
def llvalue_from_constant(c):
 
57
    try:
 
58
        T = c.concretetype
 
59
    except AttributeError:
 
60
        T = PyObjPtr
 
61
    if T == PyObjPtr and not isinstance(c.value, lltype._ptr):
 
62
        return lltype.pyobjectptr(c.value)
 
63
    else:
 
64
        if T == lltype.Void:
 
65
            return None
 
66
        else:
 
67
            assert lltype.typeOf(c.value) == T
 
68
            return c.value
 
69
 
 
70
 
 
71
class CNameManager(NameManager):
 
72
    def __init__(self, global_prefix='pypy_'):
 
73
        NameManager.__init__(self, global_prefix=global_prefix)
 
74
        # keywords cannot be reused.  This is the C99 draft's list.
 
75
        self.make_reserved_names('''
 
76
           auto      enum      restrict  unsigned
 
77
           break     extern    return    void
 
78
           case      float     short     volatile
 
79
           char      for       signed    while
 
80
           const     goto      sizeof    _Bool
 
81
           continue  if        static    _Complex
 
82
           default   inline    struct    _Imaginary
 
83
           do        int       switch
 
84
           double    long      typedef
 
85
           else      register  union
 
86
           ''')
 
87
 
 
88
def _char_repr(c):
 
89
    if c in '\\"': return '\\' + c
 
90
    if ' ' <= c < '\x7F': return c
 
91
    return '\\%03o' % ord(c)
 
92
 
 
93
def _line_repr(s):
 
94
    return ''.join([_char_repr(c) for c in s])
 
95
 
 
96
 
 
97
def c_string_constant(s):
 
98
    '''Returns a " "-delimited string literal for C.'''
 
99
    lines = []
 
100
    for i in range(0, len(s), 64):
 
101
        lines.append('"%s"' % _line_repr(s[i:i+64]))
 
102
    return '\n'.join(lines)
 
103
 
 
104
 
 
105
def c_char_array_constant(s):
 
106
    '''Returns an initializer for a constant char[N] array,
 
107
    where N is exactly len(s).  This is either a " "-delimited
 
108
    string or a { }-delimited array of small integers.
 
109
    '''
 
110
    if s.endswith('\x00') and len(s) < 1024:
 
111
        # C++ is stricted than C: we can only use a " " literal
 
112
        # if the last character is NULL, because such a literal
 
113
        # always has an extra implicit NULL terminator.
 
114
        return c_string_constant(s[:-1])
 
115
    else:
 
116
        lines = []
 
117
        for i in range(0, len(s), 20):
 
118
            lines.append(','.join([str(ord(c)) for c in s[i:i+20]]))
 
119
        if len(lines) > 1:
 
120
            return '{\n%s}' % ',\n'.join(lines)
 
121
        else:
 
122
            return '{%s}' % ', '.join(lines)
 
123
 
 
124
 
 
125
##def gen_assignments(assignments):
 
126
##    # Generate a sequence of assignments that is possibly reordered
 
127
##    # to avoid clashes -- i.e. do the equivalent of a tuple assignment,
 
128
##    # reading all sources first, writing all targets next, but optimized
 
129
 
 
130
##    allsources = []
 
131
##    src2dest = {}
 
132
##    types = {}
 
133
##    for typename, dest, src in assignments:
 
134
##        if src != dest:   # ignore 'v=v;'
 
135
##            allsources.append(src)
 
136
##            src2dest.setdefault(src, []).append(dest)
 
137
##            types[dest] = typename
 
138
 
 
139
##    for starting in allsources:
 
140
##        # starting from some starting variable, follow a chain of assignments
 
141
##        #     'vn=vn-1; ...; v3=v2; v2=v1; v1=starting;'
 
142
##        v = starting
 
143
##        srcchain = []
 
144
##        while src2dest.get(v):
 
145
##            srcchain.append(v)
 
146
##            v = src2dest[v].pop(0)
 
147
##            if v == starting:
 
148
##                break    # loop
 
149
##        if not srcchain:
 
150
##            continue   # already done in a previous chain
 
151
##        srcchain.reverse()   # ['vn-1', ..., 'v2', 'v1', 'starting']
 
152
##        code = []
 
153
##        for pair in zip([v] + srcchain[:-1], srcchain):
 
154
##            code.append('%s = %s;' % pair)
 
155
##        if v == starting:
 
156
##            # assignment loop 'starting=vn-1; ...; v2=v1; v1=starting;'
 
157
##            typename = types[starting]
 
158
##            tmpdecl = cdecl(typename, 'tmp')
 
159
##            code.insert(0, '{ %s = %s;' % (tmpdecl, starting))
 
160
##            code[-1] = '%s = tmp; }' % (srcchain[-2],)
 
161
##        yield ' '.join(code)
 
162
 
 
163
def gen_assignments(assignments):
 
164
    # Generate a sequence of assignments that is possibly reordered
 
165
    # to avoid clashes -- i.e. do the equivalent of a tuple assignment,
 
166
    # reading all sources first, writing all targets next, but optimized
 
167
 
 
168
    srccount = {}
 
169
    dest2src = {}
 
170
    for typename, dest, src in assignments:
 
171
        if src != dest:   # ignore 'v=v;'
 
172
            srccount[src] = srccount.get(src, 0) + 1
 
173
            dest2src[dest] = src, typename
 
174
 
 
175
    while dest2src:
 
176
        progress = False
 
177
        for dst in dest2src.keys():
 
178
            if dst not in srccount:
 
179
                src, typename = dest2src.pop(dst)
 
180
                yield '%s = %s;' % (dst, src)
 
181
                srccount[src] -= 1
 
182
                if not srccount[src]:
 
183
                    del srccount[src]
 
184
                progress = True
 
185
        if not progress:
 
186
            # we are left with only pure disjoint cycles; break them
 
187
            while dest2src:
 
188
                dst, (src, typename) = dest2src.popitem()
 
189
                assert srccount[dst] == 1
 
190
                startingpoint = dst
 
191
                tmpdecl = cdecl(typename, 'tmp')
 
192
                code = ['{ %s = %s;' % (tmpdecl, dst)]
 
193
                while src is not startingpoint:
 
194
                    code.append('%s = %s;' % (dst, src))
 
195
                    dst = src
 
196
                    src, typename = dest2src.pop(dst)
 
197
                    assert srccount[dst] == 1
 
198
                code.append('%s = tmp; }' % (dst,))
 
199
                yield ' '.join(code)
 
200
 
 
201
# logging
 
202
 
 
203
import py
 
204
from pypy.tool.ansi_print import ansi_log
 
205
log = py.log.Producer("c")
 
206
py.log.setconsumer("c", ansi_log)