Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / cython / src / Cython / Compiler / UtilNodes.py
1 #
2 # Nodes used as utilities and support for transforms etc.
3 # These often make up sets including both Nodes and ExprNodes
4 # so it is convenient to have them in a seperate module.
5 #
6
7 import Nodes
8 import ExprNodes
9 from Nodes import Node
10 from ExprNodes import AtomicExprNode
11 from PyrexTypes import c_ptr_type
12
13 class TempHandle(object):
14     # THIS IS DEPRECATED, USE LetRefNode instead
15     temp = None
16     needs_xdecref = False
17     def __init__(self, type, needs_cleanup=None):
18         self.type = type
19         if needs_cleanup is None:
20             self.needs_cleanup = type.is_pyobject
21         else:
22             self.needs_cleanup = needs_cleanup
23
24     def ref(self, pos):
25         return TempRefNode(pos, handle=self, type=self.type)
26
27     def cleanup_ref(self, pos):
28         return CleanupTempRefNode(pos, handle=self, type=self.type)
29
30 class TempRefNode(AtomicExprNode):
31     # THIS IS DEPRECATED, USE LetRefNode instead
32     # handle   TempHandle
33
34     def analyse_types(self, env):
35         assert self.type == self.handle.type
36         return self
37
38     def analyse_target_types(self, env):
39         assert self.type == self.handle.type
40         return self
41
42     def analyse_target_declaration(self, env):
43         pass
44
45     def calculate_result_code(self):
46         result = self.handle.temp
47         if result is None: result = "<error>" # might be called and overwritten
48         return result
49
50     def generate_result_code(self, code):
51         pass
52
53     def generate_assignment_code(self, rhs, code):
54         if self.type.is_pyobject:
55             rhs.make_owned_reference(code)
56             # TODO: analyse control flow to see if this is necessary
57             code.put_xdecref(self.result(), self.ctype())
58         code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
59         rhs.generate_post_assignment_code(code)
60         rhs.free_temps(code)
61
62 class CleanupTempRefNode(TempRefNode):
63     # THIS IS DEPRECATED, USE LetRefNode instead
64     # handle   TempHandle
65
66     def generate_assignment_code(self, rhs, code):
67         pass
68
69     def generate_execution_code(self, code):
70         if self.type.is_pyobject:
71             code.put_decref_clear(self.result(), self.type)
72             self.handle.needs_cleanup = False
73
74 class TempsBlockNode(Node):
75     # THIS IS DEPRECATED, USE LetNode instead
76
77     """
78     Creates a block which allocates temporary variables.
79     This is used by transforms to output constructs that need
80     to make use of a temporary variable. Simply pass the types
81     of the needed temporaries to the constructor.
82
83     The variables can be referred to using a TempRefNode
84     (which can be constructed by calling get_ref_node).
85     """
86
87     # temps   [TempHandle]
88     # body    StatNode
89
90     child_attrs = ["body"]
91
92     def generate_execution_code(self, code):
93         for handle in self.temps:
94             handle.temp = code.funcstate.allocate_temp(
95                 handle.type, manage_ref=handle.needs_cleanup)
96         self.body.generate_execution_code(code)
97         for handle in self.temps:
98             if handle.needs_cleanup:
99                 if handle.needs_xdecref:
100                     code.put_xdecref_clear(handle.temp, handle.type)
101                 else:
102                     code.put_decref_clear(handle.temp, handle.type)
103             code.funcstate.release_temp(handle.temp)
104
105     def analyse_declarations(self, env):
106         self.body.analyse_declarations(env)
107
108     def analyse_expressions(self, env):
109         self.body = self.body.analyse_expressions(env)
110         return self
111
112     def generate_function_definitions(self, env, code):
113         self.body.generate_function_definitions(env, code)
114
115     def annotate(self, code):
116         self.body.annotate(code)
117
118
119 class ResultRefNode(AtomicExprNode):
120     # A reference to the result of an expression.  The result_code
121     # must be set externally (usually a temp name).
122
123     subexprs = []
124     lhs_of_first_assignment = False
125
126     def __init__(self, expression=None, pos=None, type=None, may_hold_none=True, is_temp=False):
127         self.expression = expression
128         self.pos = None
129         self.may_hold_none = may_hold_none
130         if expression is not None:
131             self.pos = expression.pos
132             if hasattr(expression, "type"):
133                 self.type = expression.type
134         if pos is not None:
135             self.pos = pos
136         if type is not None:
137             self.type = type
138         if is_temp:
139             self.is_temp = True
140         assert self.pos is not None
141
142     def clone_node(self):
143         # nothing to do here
144         return self
145
146     def type_dependencies(self, env):
147         if self.expression:
148             return self.expression.type_dependencies(env)
149         else:
150             return ()
151
152     def analyse_types(self, env):
153         if self.expression is not None:
154             self.type = self.expression.type
155         return self
156
157     def infer_type(self, env):
158         if self.type is not None:
159             return self.type
160         if self.expression is not None:
161             if self.expression.type is not None:
162                 return self.expression.type
163             return self.expression.infer_type(env)
164         assert False, "cannot infer type of ResultRefNode"
165
166     def may_be_none(self):
167         if not self.type.is_pyobject:
168             return False
169         return self.may_hold_none
170
171     def _DISABLED_may_be_none(self):
172         # not sure if this is safe - the expression may not be the
173         # only value that gets assigned
174         if self.expression is not None:
175             return self.expression.may_be_none()
176         if self.type is not None:
177             return self.type.is_pyobject
178         return True # play safe
179
180     def is_simple(self):
181         return True
182
183     def result(self):
184         try:
185             return self.result_code
186         except AttributeError:
187             if self.expression is not None:
188                 self.result_code = self.expression.result()
189         return self.result_code
190
191     def generate_evaluation_code(self, code):
192         pass
193
194     def generate_result_code(self, code):
195         pass
196
197     def generate_disposal_code(self, code):
198         pass
199
200     def generate_assignment_code(self, rhs, code):
201         if self.type.is_pyobject:
202             rhs.make_owned_reference(code)
203             if not self.lhs_of_first_assignment:
204                 code.put_decref(self.result(), self.ctype())
205         code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
206         rhs.generate_post_assignment_code(code)
207         rhs.free_temps(code)
208
209     def allocate_temps(self, env):
210         pass
211
212     def release_temp(self, env):
213         pass
214
215     def free_temps(self, code):
216         pass
217
218
219 class LetNodeMixin:
220     def set_temp_expr(self, lazy_temp):
221         self.lazy_temp = lazy_temp
222         self.temp_expression = lazy_temp.expression
223
224     def setup_temp_expr(self, code):
225         self.temp_expression.generate_evaluation_code(code)
226         self.temp_type = self.temp_expression.type
227         if self.temp_type.is_array:
228             self.temp_type = c_ptr_type(self.temp_type.base_type)
229         self._result_in_temp = self.temp_expression.result_in_temp()
230         if self._result_in_temp:
231             self.temp = self.temp_expression.result()
232         else:
233             self.temp_expression.make_owned_reference(code)
234             self.temp = code.funcstate.allocate_temp(
235                 self.temp_type, manage_ref=True)
236             code.putln("%s = %s;" % (self.temp, self.temp_expression.result()))
237             self.temp_expression.generate_disposal_code(code)
238             self.temp_expression.free_temps(code)
239         self.lazy_temp.result_code = self.temp
240
241     def teardown_temp_expr(self, code):
242         if self._result_in_temp:
243             self.temp_expression.generate_disposal_code(code)
244             self.temp_expression.free_temps(code)
245         else:
246             if self.temp_type.is_pyobject:
247                 code.put_decref_clear(self.temp, self.temp_type)
248             code.funcstate.release_temp(self.temp)
249
250 class EvalWithTempExprNode(ExprNodes.ExprNode, LetNodeMixin):
251     # A wrapper around a subexpression that moves an expression into a
252     # temp variable and provides it to the subexpression.
253
254     subexprs = ['temp_expression', 'subexpression']
255
256     def __init__(self, lazy_temp, subexpression):
257         self.set_temp_expr(lazy_temp)
258         self.pos = subexpression.pos
259         self.subexpression = subexpression
260         # if called after type analysis, we already know the type here
261         self.type = self.subexpression.type
262
263     def infer_type(self, env):
264         return self.subexpression.infer_type(env)
265
266     def result(self):
267         return self.subexpression.result()
268
269     def analyse_types(self, env):
270         self.temp_expression = self.temp_expression.analyse_types(env)
271         self.subexpression = self.subexpression.analyse_types(env)
272         self.type = self.subexpression.type
273         return self
274
275     def free_subexpr_temps(self, code):
276         self.subexpression.free_temps(code)
277
278     def generate_subexpr_disposal_code(self, code):
279         self.subexpression.generate_disposal_code(code)
280
281     def generate_evaluation_code(self, code):
282         self.setup_temp_expr(code)
283         self.subexpression.generate_evaluation_code(code)
284         self.teardown_temp_expr(code)
285
286 LetRefNode = ResultRefNode
287
288 class LetNode(Nodes.StatNode, LetNodeMixin):
289     # Implements a local temporary variable scope. Imagine this
290     # syntax being present:
291     # let temp = VALUE:
292     #     BLOCK (can modify temp)
293     #     if temp is an object, decref
294     #
295     # Usually used after analysis phase, but forwards analysis methods
296     # to its children
297
298     child_attrs = ['temp_expression', 'body']
299
300     def __init__(self, lazy_temp, body):
301         self.set_temp_expr(lazy_temp)
302         self.pos = body.pos
303         self.body = body
304
305     def analyse_declarations(self, env):
306         self.temp_expression.analyse_declarations(env)
307         self.body.analyse_declarations(env)
308
309     def analyse_expressions(self, env):
310         self.temp_expression = self.temp_expression.analyse_expressions(env)
311         self.body = self.body.analyse_expressions(env)
312         return self
313
314     def generate_execution_code(self, code):
315         self.setup_temp_expr(code)
316         self.body.generate_execution_code(code)
317         self.teardown_temp_expr(code)
318
319     def generate_function_definitions(self, env, code):
320         self.temp_expression.generate_function_definitions(env, code)
321         self.body.generate_function_definitions(env, code)
322
323
324 class TempResultFromStatNode(ExprNodes.ExprNode):
325     # An ExprNode wrapper around a StatNode that executes the StatNode
326     # body.  Requires a ResultRefNode that it sets up to refer to its
327     # own temp result.  The StatNode must assign a value to the result
328     # node, which then becomes the result of this node.
329
330     subexprs = []
331     child_attrs = ['body']
332
333     def __init__(self, result_ref, body):
334         self.result_ref = result_ref
335         self.pos = body.pos
336         self.body = body
337         self.type = result_ref.type
338         self.is_temp = 1
339
340     def analyse_declarations(self, env):
341         self.body.analyse_declarations(env)
342
343     def analyse_types(self, env):
344         self.body = self.body.analyse_expressions(env)
345         return self
346
347     def generate_result_code(self, code):
348         self.result_ref.result_code = self.result()
349         self.body.generate_execution_code(code)