Update mojo sdk to rev 1dc8a9a5db73d3718d99917fadf31f5fb2ebad4f
[chromium-blink-merge.git] / third_party / cython / src / Cython / Compiler / UtilNodes.py
blobabd7a5c91c723cd3daef05ad4617a2884490488a
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.
7 import Nodes
8 import ExprNodes
9 from Nodes import Node
10 from ExprNodes import AtomicExprNode
11 from PyrexTypes import c_ptr_type
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
24 def ref(self, pos):
25 return TempRefNode(pos, handle=self, type=self.type)
27 def cleanup_ref(self, pos):
28 return CleanupTempRefNode(pos, handle=self, type=self.type)
30 class TempRefNode(AtomicExprNode):
31 # THIS IS DEPRECATED, USE LetRefNode instead
32 # handle TempHandle
34 def analyse_types(self, env):
35 assert self.type == self.handle.type
36 return self
38 def analyse_target_types(self, env):
39 assert self.type == self.handle.type
40 return self
42 def analyse_target_declaration(self, env):
43 pass
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
50 def generate_result_code(self, code):
51 pass
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)
62 class CleanupTempRefNode(TempRefNode):
63 # THIS IS DEPRECATED, USE LetRefNode instead
64 # handle TempHandle
66 def generate_assignment_code(self, rhs, code):
67 pass
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
74 class TempsBlockNode(Node):
75 # THIS IS DEPRECATED, USE LetNode instead
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.
83 The variables can be referred to using a TempRefNode
84 (which can be constructed by calling get_ref_node).
85 """
87 # temps [TempHandle]
88 # body StatNode
90 child_attrs = ["body"]
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)
105 def analyse_declarations(self, env):
106 self.body.analyse_declarations(env)
108 def analyse_expressions(self, env):
109 self.body = self.body.analyse_expressions(env)
110 return self
112 def generate_function_definitions(self, env, code):
113 self.body.generate_function_definitions(env, code)
115 def annotate(self, code):
116 self.body.annotate(code)
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).
123 subexprs = []
124 lhs_of_first_assignment = False
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
142 def clone_node(self):
143 # nothing to do here
144 return self
146 def type_dependencies(self, env):
147 if self.expression:
148 return self.expression.type_dependencies(env)
149 else:
150 return ()
152 def analyse_types(self, env):
153 if self.expression is not None:
154 self.type = self.expression.type
155 return self
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"
166 def may_be_none(self):
167 if not self.type.is_pyobject:
168 return False
169 return self.may_hold_none
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
180 def is_simple(self):
181 return True
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
191 def generate_evaluation_code(self, code):
192 pass
194 def generate_result_code(self, code):
195 pass
197 def generate_disposal_code(self, code):
198 pass
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)
209 def allocate_temps(self, env):
210 pass
212 def release_temp(self, env):
213 pass
215 def free_temps(self, code):
216 pass
219 class LetNodeMixin:
220 def set_temp_expr(self, lazy_temp):
221 self.lazy_temp = lazy_temp
222 self.temp_expression = lazy_temp.expression
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
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)
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.
254 subexprs = ['temp_expression', 'subexpression']
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
263 def infer_type(self, env):
264 return self.subexpression.infer_type(env)
266 def result(self):
267 return self.subexpression.result()
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
275 def free_subexpr_temps(self, code):
276 self.subexpression.free_temps(code)
278 def generate_subexpr_disposal_code(self, code):
279 self.subexpression.generate_disposal_code(code)
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)
286 LetRefNode = ResultRefNode
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
295 # Usually used after analysis phase, but forwards analysis methods
296 # to its children
298 child_attrs = ['temp_expression', 'body']
300 def __init__(self, lazy_temp, body):
301 self.set_temp_expr(lazy_temp)
302 self.pos = body.pos
303 self.body = body
305 def analyse_declarations(self, env):
306 self.temp_expression.analyse_declarations(env)
307 self.body.analyse_declarations(env)
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
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)
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)
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.
330 subexprs = []
331 child_attrs = ['body']
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
340 def analyse_declarations(self, env):
341 self.body.analyse_declarations(env)
343 def analyse_types(self, env):
344 self.body = self.body.analyse_expressions(env)
345 return self
347 def generate_result_code(self, code):
348 self.result_ref.result_code = self.result()
349 self.body.generate_execution_code(code)