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

« back to all changes in this revision

Viewing changes to pypy/translator/jvm/methods.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
"""
 
2
 
 
3
Special methods which we hand-generate, such as toString(), equals(), and hash().
 
4
 
 
5
These are generally added to methods listing of node.Class, and the
 
6
only requirement is that they must have a render(self, gen) method.
 
7
 
 
8
"""
 
9
 
 
10
import pypy.translator.jvm.generator as jvmgen
 
11
import pypy.translator.jvm.typesystem as jvmtype
 
12
from pypy.rpython.ootypesystem import ootype, rclass
 
13
 
 
14
class BaseDumpMethod(object):
 
15
 
 
16
    def __init__(self, db, OOCLASS, clsobj):
 
17
        self.db = db
 
18
        self.OOCLASS = OOCLASS
 
19
        self.clsobj = clsobj
 
20
        self.name = "toString"
 
21
        self.jargtypes = [clsobj]
 
22
        self.jrettype = jvmtype.jString
 
23
 
 
24
    def _print_field_value(self, fieldnm, FIELDOOTY):
 
25
        self.gen.emit(jvmgen.DUP)
 
26
        self.gen.load_this_ptr()
 
27
        fieldobj = self.clsobj.lookup_field(fieldnm)
 
28
        fieldobj.load(self.gen)
 
29
        dumpmethod = self.db.toString_method_for_ootype(FIELDOOTY)
 
30
        self.gen.emit(dumpmethod)
 
31
        self.gen.emit(jvmgen.PYPYAPPEND)
 
32
 
 
33
    def _print(self, str):
 
34
        self.gen.emit(jvmgen.DUP)
 
35
        self.gen.load_string(str)
 
36
        self.gen.emit(jvmgen.PYPYAPPEND)
 
37
 
 
38
    def render(self, gen):
 
39
        self.gen = gen
 
40
        gen.begin_function(
 
41
            self.name, (), self.jargtypes, self.jrettype, static=False)
 
42
 
 
43
        gen.new_with_jtype(jvmtype.jStringBuilder)
 
44
        self._render_guts(gen)
 
45
        gen.emit(jvmgen.OBJTOSTRING)
 
46
        gen.emit(jvmgen.RETURN.for_type(jvmtype.jString))
 
47
        gen.end_function()
 
48
        self.gen = None
 
49
 
 
50
class InstanceDumpMethod(BaseDumpMethod):
 
51
 
 
52
    def _render_guts(self, gen):
 
53
        clsobj = self.clsobj
 
54
        genprint = self._print
 
55
 
 
56
        # Start the dump
 
57
        genprint("InstanceWrapper(")
 
58
        genprint("'" + self.OOCLASS._name + "', ")
 
59
        genprint("{")
 
60
 
 
61
        for fieldnm, (FIELDOOTY, fielddef) in self.OOCLASS._fields.iteritems():
 
62
 
 
63
            if FIELDOOTY is ootype.Void: continue
 
64
 
 
65
            genprint('"'+fieldnm+'":')
 
66
 
 
67
            print "fieldnm=%r fieldty=%r" % (fieldnm, FIELDOOTY)
 
68
 
 
69
            # Print the value of the field:
 
70
            self._print_field_value(fieldnm, FIELDOOTY)
 
71
 
 
72
        # Dump close
 
73
        genprint("})")
 
74
        
 
75
class RecordDumpMethod(BaseDumpMethod):
 
76
 
 
77
    def _render_guts(self, gen):
 
78
        clsobj = self.clsobj
 
79
        genprint = self._print
 
80
 
 
81
        # We only render records that represent tuples:
 
82
        # In that case, the field names look like item0, item1, etc
 
83
        # Otherwise, we just do nothing... this is because we
 
84
        # never return records that do not represent tuples from
 
85
        # a testing function
 
86
        for f_name in self.OOCLASS._fields:
 
87
            if not f_name.startswith('item'):
 
88
                return
 
89
 
 
90
        # Start the dump
 
91
        genprint("StructTuple((")
 
92
 
 
93
        numfields = len(self.OOCLASS._fields)
 
94
        for i in range(numfields):
 
95
            f_name = 'item%d' % i
 
96
            FIELD_TYPE, f_default = self.OOCLASS._fields[f_name]
 
97
            if FIELD_TYPE is ootype.Void:
 
98
                continue
 
99
 
 
100
            # Print the value of the field:
 
101
            self._print_field_value(f_name, FIELD_TYPE)
 
102
            genprint(',')
 
103
 
 
104
        # Decrement indent and dump close
 
105
        genprint("))")
 
106
 
 
107
class ConstantStringDumpMethod(BaseDumpMethod):
 
108
    """ Just prints out a string """
 
109
 
 
110
    def __init__(self, clsobj, str):
 
111
        BaseDumpMethod.__init__(self, None, None, clsobj)
 
112
        self.constant_string = str
 
113
 
 
114
    def _render_guts(self, gen):
 
115
        genprint = self._print
 
116
        genprint("'" + self.constant_string + "'")
 
117
 
 
118
class DeepEqualsMethod(object):
 
119
 
 
120
    def __init__(self, db, OOCLASS, clsobj):
 
121
        self.db = db
 
122
        self.OOCLASS = OOCLASS
 
123
        self.clsobj = clsobj
 
124
        self.name = "equals"
 
125
        self.jargtypes = [clsobj, jvmtype.jObject]
 
126
        self.jrettype = jvmtype.jBool
 
127
 
 
128
    def render(self, gen):
 
129
        self.gen = gen
 
130
        gen.begin_function(
 
131
            self.name, (), self.jargtypes, self.jrettype, static=False)
 
132
 
 
133
        # Label to branch to should the items prove to be unequal
 
134
        unequal_lbl = gen.unique_label('unequal')
 
135
 
 
136
        gen.add_comment('check that the argument is of the correct type')
 
137
        gen.load_jvm_var(self.clsobj, 1)
 
138
        gen.instanceof(self.OOCLASS)
 
139
        gen.goto_if_false(unequal_lbl)
 
140
 
 
141
        gen.add_comment('Cast it to the right type:')
 
142
        gen.load_jvm_var(self.clsobj, 1)
 
143
        gen.downcast(self.OOCLASS)
 
144
        gen.store_jvm_var(self.clsobj, 1)
 
145
        
 
146
        # If so, compare field by field
 
147
        for fieldnm, (FIELDOOTY, fielddef) in self.OOCLASS._fields.iteritems():
 
148
            if FIELDOOTY is ootype.Void: continue
 
149
            fieldobj = self.clsobj.lookup_field(fieldnm)
 
150
 
 
151
            gen.add_comment('Compare field %s of type %s' % (fieldnm, FIELDOOTY))
 
152
 
 
153
            # Load the field from both this and the argument:
 
154
            gen.load_jvm_var(self.clsobj, 0)
 
155
            gen.emit(fieldobj)
 
156
            gen.load_jvm_var(self.clsobj, 1)
 
157
            gen.emit(fieldobj)
 
158
 
 
159
            # And compare them:
 
160
            gen.compare_values(FIELDOOTY, unequal_lbl)
 
161
 
 
162
        # Return true or false as appropriate
 
163
        gen.push_primitive_constant(ootype.Bool, True)
 
164
        gen.return_val(jvmtype.jBool)
 
165
        gen.mark(unequal_lbl)
 
166
        gen.push_primitive_constant(ootype.Bool, False)
 
167
        gen.return_val(jvmtype.jBool)
 
168
 
 
169
        gen.end_function()
 
170
 
 
171
class DeepHashMethod(object):
 
172
 
 
173
    def __init__(self, db, OOCLASS, clsobj):
 
174
        self.db = db
 
175
        self.OOCLASS = OOCLASS
 
176
        self.clsobj = clsobj
 
177
        self.name = "hashCode"
 
178
        self.jargtypes = [clsobj]
 
179
        self.jrettype = jvmtype.jInt
 
180
 
 
181
    def render(self, gen):
 
182
        self.gen = gen
 
183
        gen.begin_function(
 
184
            self.name, (), self.jargtypes, self.jrettype, static=False)
 
185
 
 
186
        # Initial hash: 0
 
187
        gen.push_primitive_constant(ootype.Signed, 0)
 
188
 
 
189
        # Get hash of each field
 
190
        for fieldnm, (FIELDOOTY, fielddef) in self.OOCLASS._fields.iteritems():
 
191
            if FIELDOOTY is ootype.Void: continue
 
192
            fieldobj = self.clsobj.lookup_field(fieldnm)
 
193
 
 
194
            gen.add_comment('Hash field %s of type %s' % (fieldnm, FIELDOOTY))
 
195
 
 
196
            # Load the field and hash it:
 
197
            gen.load_jvm_var(self.clsobj, 0)
 
198
            gen.emit(fieldobj)
 
199
            gen.hash_value(FIELDOOTY)
 
200
 
 
201
            # XOR that with the main hash
 
202
            gen.emit(jvmgen.IXOR)
 
203
 
 
204
        # Return the final hash
 
205
        gen.return_val(jvmtype.jInt)
 
206
 
 
207
        gen.end_function()
 
208