aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Compiler/UtilNodes.py
diff options
context:
space:
mode:
authorAnton Samokhvalov <pg83@yandex.ru>2022-02-10 16:45:17 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:17 +0300
commitd3a398281c6fd1d3672036cb2d63f842d2cb28c5 (patch)
treedd4bd3ca0f36b817e96812825ffaf10d645803f2 /contrib/tools/cython/Cython/Compiler/UtilNodes.py
parent72cb13b4aff9bc9cf22e49251bc8fd143f82538f (diff)
downloadydb-d3a398281c6fd1d3672036cb2d63f842d2cb28c5.tar.gz
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/tools/cython/Cython/Compiler/UtilNodes.py')
-rw-r--r--contrib/tools/cython/Cython/Compiler/UtilNodes.py674
1 files changed, 337 insertions, 337 deletions
diff --git a/contrib/tools/cython/Cython/Compiler/UtilNodes.py b/contrib/tools/cython/Cython/Compiler/UtilNodes.py
index 0b8db28207..c41748ace0 100644
--- a/contrib/tools/cython/Cython/Compiler/UtilNodes.py
+++ b/contrib/tools/cython/Cython/Compiler/UtilNodes.py
@@ -1,359 +1,359 @@
-#
-# Nodes used as utilities and support for transforms etc.
-# These often make up sets including both Nodes and ExprNodes
+#
+# Nodes used as utilities and support for transforms etc.
+# These often make up sets including both Nodes and ExprNodes
# so it is convenient to have them in a separate module.
-#
-
-from __future__ import absolute_import
-
-from . import Nodes
-from . import ExprNodes
-from .Nodes import Node
-from .ExprNodes import AtomicExprNode
-from .PyrexTypes import c_ptr_type
-
-
-class TempHandle(object):
- # THIS IS DEPRECATED, USE LetRefNode instead
- temp = None
- needs_xdecref = False
- def __init__(self, type, needs_cleanup=None):
- self.type = type
- if needs_cleanup is None:
- self.needs_cleanup = type.is_pyobject
- else:
- self.needs_cleanup = needs_cleanup
-
- def ref(self, pos):
- return TempRefNode(pos, handle=self, type=self.type)
-
-
-class TempRefNode(AtomicExprNode):
- # THIS IS DEPRECATED, USE LetRefNode instead
- # handle TempHandle
-
- def analyse_types(self, env):
- assert self.type == self.handle.type
- return self
-
- def analyse_target_types(self, env):
- assert self.type == self.handle.type
- return self
-
- def analyse_target_declaration(self, env):
- pass
-
- def calculate_result_code(self):
- result = self.handle.temp
- if result is None: result = "<error>" # might be called and overwritten
- return result
-
- def generate_result_code(self, code):
- pass
-
+#
+
+from __future__ import absolute_import
+
+from . import Nodes
+from . import ExprNodes
+from .Nodes import Node
+from .ExprNodes import AtomicExprNode
+from .PyrexTypes import c_ptr_type
+
+
+class TempHandle(object):
+ # THIS IS DEPRECATED, USE LetRefNode instead
+ temp = None
+ needs_xdecref = False
+ def __init__(self, type, needs_cleanup=None):
+ self.type = type
+ if needs_cleanup is None:
+ self.needs_cleanup = type.is_pyobject
+ else:
+ self.needs_cleanup = needs_cleanup
+
+ def ref(self, pos):
+ return TempRefNode(pos, handle=self, type=self.type)
+
+
+class TempRefNode(AtomicExprNode):
+ # THIS IS DEPRECATED, USE LetRefNode instead
+ # handle TempHandle
+
+ def analyse_types(self, env):
+ assert self.type == self.handle.type
+ return self
+
+ def analyse_target_types(self, env):
+ assert self.type == self.handle.type
+ return self
+
+ def analyse_target_declaration(self, env):
+ pass
+
+ def calculate_result_code(self):
+ result = self.handle.temp
+ if result is None: result = "<error>" # might be called and overwritten
+ return result
+
+ def generate_result_code(self, code):
+ pass
+
def generate_assignment_code(self, rhs, code, overloaded_assignment=False):
- if self.type.is_pyobject:
- rhs.make_owned_reference(code)
- # TODO: analyse control flow to see if this is necessary
- code.put_xdecref(self.result(), self.ctype())
+ if self.type.is_pyobject:
+ rhs.make_owned_reference(code)
+ # TODO: analyse control flow to see if this is necessary
+ code.put_xdecref(self.result(), self.ctype())
code.putln('%s = %s;' % (
self.result(),
rhs.result() if overloaded_assignment else rhs.result_as(self.ctype()),
))
- rhs.generate_post_assignment_code(code)
- rhs.free_temps(code)
-
-
-class TempsBlockNode(Node):
- # THIS IS DEPRECATED, USE LetNode instead
-
- """
- Creates a block which allocates temporary variables.
- This is used by transforms to output constructs that need
- to make use of a temporary variable. Simply pass the types
- of the needed temporaries to the constructor.
-
- The variables can be referred to using a TempRefNode
- (which can be constructed by calling get_ref_node).
- """
-
- # temps [TempHandle]
- # body StatNode
-
- child_attrs = ["body"]
-
- def generate_execution_code(self, code):
- for handle in self.temps:
- handle.temp = code.funcstate.allocate_temp(
- handle.type, manage_ref=handle.needs_cleanup)
- self.body.generate_execution_code(code)
- for handle in self.temps:
- if handle.needs_cleanup:
- if handle.needs_xdecref:
- code.put_xdecref_clear(handle.temp, handle.type)
- else:
- code.put_decref_clear(handle.temp, handle.type)
- code.funcstate.release_temp(handle.temp)
-
- def analyse_declarations(self, env):
- self.body.analyse_declarations(env)
-
- def analyse_expressions(self, env):
- self.body = self.body.analyse_expressions(env)
- return self
-
- def generate_function_definitions(self, env, code):
- self.body.generate_function_definitions(env, code)
-
- def annotate(self, code):
- self.body.annotate(code)
-
-
-class ResultRefNode(AtomicExprNode):
- # A reference to the result of an expression. The result_code
- # must be set externally (usually a temp name).
-
- subexprs = []
- lhs_of_first_assignment = False
-
- def __init__(self, expression=None, pos=None, type=None, may_hold_none=True, is_temp=False):
- self.expression = expression
- self.pos = None
- self.may_hold_none = may_hold_none
- if expression is not None:
- self.pos = expression.pos
- if hasattr(expression, "type"):
- self.type = expression.type
- if pos is not None:
- self.pos = pos
- if type is not None:
- self.type = type
- if is_temp:
- self.is_temp = True
- assert self.pos is not None
-
- def clone_node(self):
- # nothing to do here
- return self
-
- def type_dependencies(self, env):
- if self.expression:
- return self.expression.type_dependencies(env)
- else:
- return ()
-
+ rhs.generate_post_assignment_code(code)
+ rhs.free_temps(code)
+
+
+class TempsBlockNode(Node):
+ # THIS IS DEPRECATED, USE LetNode instead
+
+ """
+ Creates a block which allocates temporary variables.
+ This is used by transforms to output constructs that need
+ to make use of a temporary variable. Simply pass the types
+ of the needed temporaries to the constructor.
+
+ The variables can be referred to using a TempRefNode
+ (which can be constructed by calling get_ref_node).
+ """
+
+ # temps [TempHandle]
+ # body StatNode
+
+ child_attrs = ["body"]
+
+ def generate_execution_code(self, code):
+ for handle in self.temps:
+ handle.temp = code.funcstate.allocate_temp(
+ handle.type, manage_ref=handle.needs_cleanup)
+ self.body.generate_execution_code(code)
+ for handle in self.temps:
+ if handle.needs_cleanup:
+ if handle.needs_xdecref:
+ code.put_xdecref_clear(handle.temp, handle.type)
+ else:
+ code.put_decref_clear(handle.temp, handle.type)
+ code.funcstate.release_temp(handle.temp)
+
+ def analyse_declarations(self, env):
+ self.body.analyse_declarations(env)
+
+ def analyse_expressions(self, env):
+ self.body = self.body.analyse_expressions(env)
+ return self
+
+ def generate_function_definitions(self, env, code):
+ self.body.generate_function_definitions(env, code)
+
+ def annotate(self, code):
+ self.body.annotate(code)
+
+
+class ResultRefNode(AtomicExprNode):
+ # A reference to the result of an expression. The result_code
+ # must be set externally (usually a temp name).
+
+ subexprs = []
+ lhs_of_first_assignment = False
+
+ def __init__(self, expression=None, pos=None, type=None, may_hold_none=True, is_temp=False):
+ self.expression = expression
+ self.pos = None
+ self.may_hold_none = may_hold_none
+ if expression is not None:
+ self.pos = expression.pos
+ if hasattr(expression, "type"):
+ self.type = expression.type
+ if pos is not None:
+ self.pos = pos
+ if type is not None:
+ self.type = type
+ if is_temp:
+ self.is_temp = True
+ assert self.pos is not None
+
+ def clone_node(self):
+ # nothing to do here
+ return self
+
+ def type_dependencies(self, env):
+ if self.expression:
+ return self.expression.type_dependencies(env)
+ else:
+ return ()
+
def update_expression(self, expression):
self.expression = expression
if hasattr(expression, "type"):
self.type = expression.type
- def analyse_types(self, env):
- if self.expression is not None:
+ def analyse_types(self, env):
+ if self.expression is not None:
if not self.expression.type:
self.expression = self.expression.analyse_types(env)
- self.type = self.expression.type
- return self
-
- def infer_type(self, env):
- if self.type is not None:
- return self.type
- if self.expression is not None:
- if self.expression.type is not None:
- return self.expression.type
- return self.expression.infer_type(env)
- assert False, "cannot infer type of ResultRefNode"
-
- def may_be_none(self):
- if not self.type.is_pyobject:
- return False
- return self.may_hold_none
-
- def _DISABLED_may_be_none(self):
- # not sure if this is safe - the expression may not be the
- # only value that gets assigned
- if self.expression is not None:
- return self.expression.may_be_none()
- if self.type is not None:
- return self.type.is_pyobject
- return True # play safe
-
- def is_simple(self):
- return True
-
- def result(self):
- try:
- return self.result_code
- except AttributeError:
- if self.expression is not None:
- self.result_code = self.expression.result()
- return self.result_code
-
- def generate_evaluation_code(self, code):
- pass
-
- def generate_result_code(self, code):
- pass
-
- def generate_disposal_code(self, code):
- pass
-
+ self.type = self.expression.type
+ return self
+
+ def infer_type(self, env):
+ if self.type is not None:
+ return self.type
+ if self.expression is not None:
+ if self.expression.type is not None:
+ return self.expression.type
+ return self.expression.infer_type(env)
+ assert False, "cannot infer type of ResultRefNode"
+
+ def may_be_none(self):
+ if not self.type.is_pyobject:
+ return False
+ return self.may_hold_none
+
+ def _DISABLED_may_be_none(self):
+ # not sure if this is safe - the expression may not be the
+ # only value that gets assigned
+ if self.expression is not None:
+ return self.expression.may_be_none()
+ if self.type is not None:
+ return self.type.is_pyobject
+ return True # play safe
+
+ def is_simple(self):
+ return True
+
+ def result(self):
+ try:
+ return self.result_code
+ except AttributeError:
+ if self.expression is not None:
+ self.result_code = self.expression.result()
+ return self.result_code
+
+ def generate_evaluation_code(self, code):
+ pass
+
+ def generate_result_code(self, code):
+ pass
+
+ def generate_disposal_code(self, code):
+ pass
+
def generate_assignment_code(self, rhs, code, overloaded_assignment=False):
- if self.type.is_pyobject:
- rhs.make_owned_reference(code)
- if not self.lhs_of_first_assignment:
- code.put_decref(self.result(), self.ctype())
+ if self.type.is_pyobject:
+ rhs.make_owned_reference(code)
+ if not self.lhs_of_first_assignment:
+ code.put_decref(self.result(), self.ctype())
code.putln('%s = %s;' % (
self.result(),
rhs.result() if overloaded_assignment else rhs.result_as(self.ctype()),
))
- rhs.generate_post_assignment_code(code)
- rhs.free_temps(code)
-
- def allocate_temps(self, env):
- pass
-
- def release_temp(self, env):
- pass
-
- def free_temps(self, code):
- pass
-
-
-class LetNodeMixin:
- def set_temp_expr(self, lazy_temp):
- self.lazy_temp = lazy_temp
- self.temp_expression = lazy_temp.expression
-
- def setup_temp_expr(self, code):
- self.temp_expression.generate_evaluation_code(code)
- self.temp_type = self.temp_expression.type
- if self.temp_type.is_array:
- self.temp_type = c_ptr_type(self.temp_type.base_type)
- self._result_in_temp = self.temp_expression.result_in_temp()
- if self._result_in_temp:
- self.temp = self.temp_expression.result()
- else:
- self.temp_expression.make_owned_reference(code)
- self.temp = code.funcstate.allocate_temp(
- self.temp_type, manage_ref=True)
- code.putln("%s = %s;" % (self.temp, self.temp_expression.result()))
- self.temp_expression.generate_disposal_code(code)
- self.temp_expression.free_temps(code)
- self.lazy_temp.result_code = self.temp
-
- def teardown_temp_expr(self, code):
- if self._result_in_temp:
- self.temp_expression.generate_disposal_code(code)
- self.temp_expression.free_temps(code)
- else:
- if self.temp_type.is_pyobject:
- code.put_decref_clear(self.temp, self.temp_type)
- code.funcstate.release_temp(self.temp)
-
-
-class EvalWithTempExprNode(ExprNodes.ExprNode, LetNodeMixin):
- # A wrapper around a subexpression that moves an expression into a
- # temp variable and provides it to the subexpression.
-
- subexprs = ['temp_expression', 'subexpression']
-
- def __init__(self, lazy_temp, subexpression):
- self.set_temp_expr(lazy_temp)
- self.pos = subexpression.pos
- self.subexpression = subexpression
- # if called after type analysis, we already know the type here
- self.type = self.subexpression.type
-
- def infer_type(self, env):
- return self.subexpression.infer_type(env)
-
+ rhs.generate_post_assignment_code(code)
+ rhs.free_temps(code)
+
+ def allocate_temps(self, env):
+ pass
+
+ def release_temp(self, env):
+ pass
+
+ def free_temps(self, code):
+ pass
+
+
+class LetNodeMixin:
+ def set_temp_expr(self, lazy_temp):
+ self.lazy_temp = lazy_temp
+ self.temp_expression = lazy_temp.expression
+
+ def setup_temp_expr(self, code):
+ self.temp_expression.generate_evaluation_code(code)
+ self.temp_type = self.temp_expression.type
+ if self.temp_type.is_array:
+ self.temp_type = c_ptr_type(self.temp_type.base_type)
+ self._result_in_temp = self.temp_expression.result_in_temp()
+ if self._result_in_temp:
+ self.temp = self.temp_expression.result()
+ else:
+ self.temp_expression.make_owned_reference(code)
+ self.temp = code.funcstate.allocate_temp(
+ self.temp_type, manage_ref=True)
+ code.putln("%s = %s;" % (self.temp, self.temp_expression.result()))
+ self.temp_expression.generate_disposal_code(code)
+ self.temp_expression.free_temps(code)
+ self.lazy_temp.result_code = self.temp
+
+ def teardown_temp_expr(self, code):
+ if self._result_in_temp:
+ self.temp_expression.generate_disposal_code(code)
+ self.temp_expression.free_temps(code)
+ else:
+ if self.temp_type.is_pyobject:
+ code.put_decref_clear(self.temp, self.temp_type)
+ code.funcstate.release_temp(self.temp)
+
+
+class EvalWithTempExprNode(ExprNodes.ExprNode, LetNodeMixin):
+ # A wrapper around a subexpression that moves an expression into a
+ # temp variable and provides it to the subexpression.
+
+ subexprs = ['temp_expression', 'subexpression']
+
+ def __init__(self, lazy_temp, subexpression):
+ self.set_temp_expr(lazy_temp)
+ self.pos = subexpression.pos
+ self.subexpression = subexpression
+ # if called after type analysis, we already know the type here
+ self.type = self.subexpression.type
+
+ def infer_type(self, env):
+ return self.subexpression.infer_type(env)
+
def may_be_none(self):
return self.subexpression.may_be_none()
- def result(self):
- return self.subexpression.result()
-
- def analyse_types(self, env):
- self.temp_expression = self.temp_expression.analyse_types(env)
+ def result(self):
+ return self.subexpression.result()
+
+ def analyse_types(self, env):
+ self.temp_expression = self.temp_expression.analyse_types(env)
self.lazy_temp.update_expression(self.temp_expression) # overwrite in case it changed
- self.subexpression = self.subexpression.analyse_types(env)
- self.type = self.subexpression.type
- return self
-
- def free_subexpr_temps(self, code):
- self.subexpression.free_temps(code)
-
- def generate_subexpr_disposal_code(self, code):
- self.subexpression.generate_disposal_code(code)
-
- def generate_evaluation_code(self, code):
- self.setup_temp_expr(code)
- self.subexpression.generate_evaluation_code(code)
- self.teardown_temp_expr(code)
-
-
-LetRefNode = ResultRefNode
-
-
-class LetNode(Nodes.StatNode, LetNodeMixin):
- # Implements a local temporary variable scope. Imagine this
- # syntax being present:
- # let temp = VALUE:
- # BLOCK (can modify temp)
- # if temp is an object, decref
- #
- # Usually used after analysis phase, but forwards analysis methods
- # to its children
-
- child_attrs = ['temp_expression', 'body']
-
- def __init__(self, lazy_temp, body):
- self.set_temp_expr(lazy_temp)
- self.pos = body.pos
- self.body = body
-
- def analyse_declarations(self, env):
- self.temp_expression.analyse_declarations(env)
- self.body.analyse_declarations(env)
-
- def analyse_expressions(self, env):
- self.temp_expression = self.temp_expression.analyse_expressions(env)
- self.body = self.body.analyse_expressions(env)
- return self
-
- def generate_execution_code(self, code):
- self.setup_temp_expr(code)
- self.body.generate_execution_code(code)
- self.teardown_temp_expr(code)
-
- def generate_function_definitions(self, env, code):
- self.temp_expression.generate_function_definitions(env, code)
- self.body.generate_function_definitions(env, code)
-
-
-class TempResultFromStatNode(ExprNodes.ExprNode):
- # An ExprNode wrapper around a StatNode that executes the StatNode
- # body. Requires a ResultRefNode that it sets up to refer to its
- # own temp result. The StatNode must assign a value to the result
- # node, which then becomes the result of this node.
-
- subexprs = []
- child_attrs = ['body']
-
- def __init__(self, result_ref, body):
- self.result_ref = result_ref
- self.pos = body.pos
- self.body = body
- self.type = result_ref.type
- self.is_temp = 1
-
- def analyse_declarations(self, env):
- self.body.analyse_declarations(env)
-
- def analyse_types(self, env):
- self.body = self.body.analyse_expressions(env)
- return self
-
- def generate_result_code(self, code):
- self.result_ref.result_code = self.result()
- self.body.generate_execution_code(code)
+ self.subexpression = self.subexpression.analyse_types(env)
+ self.type = self.subexpression.type
+ return self
+
+ def free_subexpr_temps(self, code):
+ self.subexpression.free_temps(code)
+
+ def generate_subexpr_disposal_code(self, code):
+ self.subexpression.generate_disposal_code(code)
+
+ def generate_evaluation_code(self, code):
+ self.setup_temp_expr(code)
+ self.subexpression.generate_evaluation_code(code)
+ self.teardown_temp_expr(code)
+
+
+LetRefNode = ResultRefNode
+
+
+class LetNode(Nodes.StatNode, LetNodeMixin):
+ # Implements a local temporary variable scope. Imagine this
+ # syntax being present:
+ # let temp = VALUE:
+ # BLOCK (can modify temp)
+ # if temp is an object, decref
+ #
+ # Usually used after analysis phase, but forwards analysis methods
+ # to its children
+
+ child_attrs = ['temp_expression', 'body']
+
+ def __init__(self, lazy_temp, body):
+ self.set_temp_expr(lazy_temp)
+ self.pos = body.pos
+ self.body = body
+
+ def analyse_declarations(self, env):
+ self.temp_expression.analyse_declarations(env)
+ self.body.analyse_declarations(env)
+
+ def analyse_expressions(self, env):
+ self.temp_expression = self.temp_expression.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
+ return self
+
+ def generate_execution_code(self, code):
+ self.setup_temp_expr(code)
+ self.body.generate_execution_code(code)
+ self.teardown_temp_expr(code)
+
+ def generate_function_definitions(self, env, code):
+ self.temp_expression.generate_function_definitions(env, code)
+ self.body.generate_function_definitions(env, code)
+
+
+class TempResultFromStatNode(ExprNodes.ExprNode):
+ # An ExprNode wrapper around a StatNode that executes the StatNode
+ # body. Requires a ResultRefNode that it sets up to refer to its
+ # own temp result. The StatNode must assign a value to the result
+ # node, which then becomes the result of this node.
+
+ subexprs = []
+ child_attrs = ['body']
+
+ def __init__(self, result_ref, body):
+ self.result_ref = result_ref
+ self.pos = body.pos
+ self.body = body
+ self.type = result_ref.type
+ self.is_temp = 1
+
+ def analyse_declarations(self, env):
+ self.body.analyse_declarations(env)
+
+ def analyse_types(self, env):
+ self.body = self.body.analyse_expressions(env)
+ return self
+
+ def generate_result_code(self, code):
+ self.result_ref.result_code = self.result()
+ self.body.generate_execution_code(code)