# Path: src/som/interpreter/ast/nodes/contextual_node.py
# class ContextualNode(ExpressionNode):
# 
#     _immutable_fields_ = ["_context_level"]
# 
#     def __init__(self, context_level, source_section = None):
#         ExpressionNode.__init__(self, source_section)
#         assert context_level >= 0
#         self._context_level = context_level
# 
#     def get_context_level(self):
#         return self._context_level
# 
#     def accesses_outer_context(self):
#         return self._context_level > 0
# 
#     @unroll_safe
#     def determine_block(self, frame):
#         assert self._context_level > 0
# 
#         block = frame.get_self()
#         for i in range(0, self._context_level - 1):
#             block = block.get_outer_self()
#         return block
# 
#     @unroll_safe
#     def determine_outer_self(self, frame):
#         outer_self = frame.get_self()
#         for i in range(0, self._context_level):
#             outer_self = outer_self.get_outer_self()
#         return outer_self
# 
# Path: src/som/interpreter/ast/nodes/dispatch.py
# def lookup_and_send(receiver, selector_string, arguments, universe):
#     selector = universe.symbol_for(selector_string)
#     invokable = receiver.get_class(universe).lookup_invokable(selector)
#     return invokable.invoke(receiver, arguments)
# 
# Path: src/som/interpreter/ast/nodes/expression_node.py
# class ExpressionNode(Node):
# 
#     def __init__(self, source_section):
#         Node.__init__(self, source_section)
# 
#     def is_super_node(self):
#         return False
# 
# Path: src/som/interpreter/control_flow.py
# class ReturnException(Exception):
#     
#     _immutable_fields_ = ["_result", "_target"]
#     
#     def __init__(self, result, target):
#         self._result = result
#         self._target = target
#     
#     def get_result(self):
#         return self._result
#     
#     def has_reached_target(self, current):
#         return current is self._target
# 
#     def __str__(self):
#         return "ReturnEx(%s)" % self._result


from .contextual_node import ContextualNode
from .dispatch import lookup_and_send
from .expression_node import ExpressionNode
from ...control_flow import ReturnException



class ReturnNonLocalNode(ContextualNode):

    _immutable_fields_ = ['_expr?', '_universe']
    _child_nodes_      = ['_expr']

    def __init__(self, context_level, expr, universe, source_section = None):
        ContextualNode.__init__(self, context_level, source_section)
        self._expr     = self.adopt_child(expr)
        self._universe = universe

    def execute(self, frame):
        result = self._expr.execute(frame)
        block = self.determine_block(frame)

        if block.is_outer_on_stack():

# Path: src/som/interpreter/ast/nodes/contextual_node.py
# class ContextualNode(ExpressionNode):
# 
#     _immutable_fields_ = ["_context_level"]
# 
#     def __init__(self, context_level, source_section = None):
#         ExpressionNode.__init__(self, source_section)
#         assert context_level >= 0
#         self._context_level = context_level
# 
#     def get_context_level(self):
#         return self._context_level
# 
#     def accesses_outer_context(self):
#         return self._context_level > 0
# 
#     @unroll_safe
#     def determine_block(self, frame):
#         assert self._context_level > 0
# 
#         block = frame.get_self()
#         for i in range(0, self._context_level - 1):
#             block = block.get_outer_self()
#         return block
# 
#     @unroll_safe
#     def determine_outer_self(self, frame):
#         outer_self = frame.get_self()
#         for i in range(0, self._context_level):
#             outer_self = outer_self.get_outer_self()
#         return outer_self
# 
# Path: src/som/interpreter/ast/nodes/dispatch.py
# def lookup_and_send(receiver, selector_string, arguments, universe):
#     selector = universe.symbol_for(selector_string)
#     invokable = receiver.get_class(universe).lookup_invokable(selector)
#     return invokable.invoke(receiver, arguments)
# 
# Path: src/som/interpreter/ast/nodes/expression_node.py
# class ExpressionNode(Node):
# 
#     def __init__(self, source_section):
#         Node.__init__(self, source_section)
# 
#     def is_super_node(self):
#         return False
# 
# Path: src/som/interpreter/control_flow.py
# class ReturnException(Exception):
#     
#     _immutable_fields_ = ["_result", "_target"]
#     
#     def __init__(self, result, target):
#         self._result = result
#         self._target = target
#     
#     def get_result(self):
#         return self._result
#     
#     def has_reached_target(self, current):
#         return current is self._target
# 
#     def __str__(self):
#         return "ReturnEx(%s)" % self._result


# Path: src/som/interpreter/ast/nodes/return_non_local_node.py
from .contextual_node import ContextualNode
from .dispatch import lookup_and_send
from .expression_node import ExpressionNode
from ...control_flow import ReturnException




class ReturnNonLocalNode(ContextualNode):

    _immutable_fields_ = ['_expr?', '_universe']
    _child_nodes_      = ['_expr']

    def __init__(self, context_level, expr, universe, source_section = None):
        ContextualNode.__init__(self, context_level, source_section)
        self._expr     = self.adopt_child(expr)
        self._universe = universe

    def execute(self, frame):
        result = self._expr.execute(frame)
        block = self.determine_block(frame)

        if block.is_outer_on_stack():

            raise ReturnException(result, block.get_on_stack_marker())