Cython has moved to github.
cython-devel
view Cython/Compiler/UtilNodes.py @ 1470:49a8357fc01e
fixed FlattenInListTransform by providing a temp block expression that injects the temp result into a subexpression
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Sun Dec 07 21:14:13 2008 +0100 (3 years ago) |
| parents | 8b9ca1d0b023 |
| children | 5c0b99aebb9b |
line source
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 #
7 import Nodes
8 import ExprNodes
9 from Nodes import Node
10 from ExprNodes import AtomicExprNode
12 class TempHandle(object):
13 temp = None
14 needs_xdecref = False
15 def __init__(self, type):
16 self.type = type
17 self.needs_cleanup = type.is_pyobject
19 def ref(self, pos):
20 return TempRefNode(pos, handle=self, type=self.type)
22 def cleanup_ref(self, pos):
23 return CleanupTempRefNode(pos, handle=self, type=self.type)
25 class TempRefNode(AtomicExprNode):
26 # handle TempHandle
28 def analyse_types(self, env):
29 assert self.type == self.handle.type
31 def analyse_target_types(self, env):
32 assert self.type == self.handle.type
34 def analyse_target_declaration(self, env):
35 pass
37 def calculate_result_code(self):
38 result = self.handle.temp
39 if result is None: result = "<error>" # might be called and overwritten
40 return result
42 def generate_result_code(self, code):
43 pass
45 def generate_assignment_code(self, rhs, code):
46 if self.type.is_pyobject:
47 rhs.make_owned_reference(code)
48 # TODO: analyse control flow to see if this is necessary
49 code.put_xdecref(self.result(), self.ctype())
50 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
51 rhs.generate_post_assignment_code(code)
53 class CleanupTempRefNode(TempRefNode):
54 # handle TempHandle
56 def generate_assignment_code(self, rhs, code):
57 pass
59 def generate_execution_code(self, code):
60 if self.type.is_pyobject:
61 code.put_decref_clear(self.result(), self.type)
62 self.handle.needs_cleanup = False
64 class TempsBlockNode(Node):
65 """
66 Creates a block which allocates temporary variables.
67 This is used by transforms to output constructs that need
68 to make use of a temporary variable. Simply pass the types
69 of the needed temporaries to the constructor.
71 The variables can be referred to using a TempRefNode
72 (which can be constructed by calling get_ref_node).
73 """
75 # temps [TempHandle]
76 # body StatNode
78 child_attrs = ["body"]
80 def generate_execution_code(self, code):
81 for handle in self.temps:
82 handle.temp = code.funcstate.allocate_temp(
83 handle.type, manage_ref=handle.needs_cleanup)
84 self.body.generate_execution_code(code)
85 for handle in self.temps:
86 if handle.needs_cleanup:
87 if handle.needs_xdecref:
88 code.put_xdecref_clear(handle.temp, handle.type)
89 else:
90 code.put_decref_clear(handle.temp, handle.type)
91 code.funcstate.release_temp(handle.temp)
93 def analyse_control_flow(self, env):
94 self.body.analyse_control_flow(env)
96 def analyse_declarations(self, env):
97 self.body.analyse_declarations(env)
99 def analyse_expressions(self, env):
100 self.body.analyse_expressions(env)
102 def generate_function_definitions(self, env, code):
103 self.body.generate_function_definitions(env, code)
105 def annotate(self, code):
106 self.body.annotate(code)
109 class ResultRefNode(AtomicExprNode):
110 # A reference to the result of an expression. The result_code
111 # must be set externally (usually a temp name).
113 subexprs = []
115 def __init__(self, expression):
116 self.pos = expression.pos
117 self.expression = expression
119 def analyse_types(self, env):
120 self.type = self.expression.type
122 def result(self):
123 return self.result_code
125 def generate_evaluation_code(self, code):
126 pass
128 def generate_result_code(self, code):
129 pass
131 def generate_disposal_code(self, code):
132 pass
134 def allocate_temps(self, env):
135 pass
137 def release_temp(self, env):
138 pass
140 def free_temps(self, code):
141 pass
144 class TempBlockExprNode(ExprNodes.NewTempExprNode):
145 # A wrapper around a subexpression that moves an expression into a
146 # temp variable and provides it to the subexpression.
148 subexprs = ['temp_expression', 'subexpression']
150 def __init__(self, lazy_temp, subexpression):
151 self.pos = subexpression.pos
152 self.lazy_temp = lazy_temp
153 self.temp_expression = lazy_temp.expression
154 self.subexpression = subexpression
156 def result(self):
157 return self.subexpression.result()
159 def analyse_types(self, env):
160 self.temp_expression.analyse_types(env)
161 self.subexpression.analyse_types(env)
162 self.type = self.subexpression.type
164 def generate_evaluation_code(self, code):
165 self.temp_expression.generate_evaluation_code(code)
166 if self.temp_expression.is_temp:
167 temp = self.temp_expression.result()
168 else:
169 self.temp_expression.make_owned_reference(code)
170 temp = code.funcstate.allocate_temp(
171 self.temp_expression.type, manage_ref=True)
172 code.putln("%s = %s;" % (temp, self.temp_expression.result()))
173 self.lazy_temp.result_code = temp
174 self.subexpression.generate_evaluation_code(code)
175 if not self.temp_expression.is_temp:
176 code.funcstate.release_temp(temp)
