|
@@ -4,12 +4,42 @@ class KnownRequestHandled(Exception):
|
|
|
"""An exception that signifies that a known request was handled."""
|
|
|
pass
|
|
|
|
|
|
+class GeneratorStackEntry(object):
|
|
|
+ """An entry in the generator stack of a request handles."""
|
|
|
+ def __init__(self, generator):
|
|
|
+ self.generator = generator
|
|
|
+ self.pending_requests = None
|
|
|
+ self.finished_requests = True
|
|
|
+ self.replies = []
|
|
|
+ self.has_reply = False
|
|
|
+
|
|
|
+ def append_reply(self, new_reply):
|
|
|
+ """Appends a reply to the this entry's list of pending replies."""
|
|
|
+ self.replies.append(new_reply)
|
|
|
+ self.has_reply = True
|
|
|
+
|
|
|
+ def extend_replies(self, new_replies):
|
|
|
+ """Appends a list of replies to this entry's list of pending replies."""
|
|
|
+ if new_replies is not None:
|
|
|
+ self.replies.extend(new_replies)
|
|
|
+ self.has_reply = True
|
|
|
+
|
|
|
+ def step(self):
|
|
|
+ """Performs a single step: accumulated replies are fed to the generator,
|
|
|
+ which then produces requests."""
|
|
|
+ # Send the replies to the generator, and ask for new requests.
|
|
|
+ self.pending_requests = self.generator.send(self.replies if self.has_reply else None)
|
|
|
+
|
|
|
+ # Reset some data structures.
|
|
|
+ self.finished_requests = False
|
|
|
+ self.replies = []
|
|
|
+ self.has_reply = False
|
|
|
+
|
|
|
class RequestHandler(object):
|
|
|
"""A type of object that intercepts logic-related Modelverse requests, and
|
|
|
forwards Modelverse state requests."""
|
|
|
def __init__(self):
|
|
|
- # generator_stack is a stack of (generator, pending requests, request replies, has-reply)
|
|
|
- # tuples.
|
|
|
+ # generator_stack is a stack of GeneratorStackEntry values.
|
|
|
self.generator_stack = []
|
|
|
# exception_handlers is a stack of
|
|
|
# (generator_stack index, [(exception type, handler function)])
|
|
@@ -80,17 +110,15 @@ class RequestHandler(object):
|
|
|
|
|
|
def set_finished_requests_flag(self):
|
|
|
"""Sets the finished_requests flag in the top-of-stack tuple."""
|
|
|
- current_generator, requests, _, replies, has_reply = self.generator_stack[-1]
|
|
|
- self.generator_stack[-1] = (current_generator, requests, True, replies, has_reply)
|
|
|
+ self.generator_stack[-1].finished_requests = True
|
|
|
|
|
|
def has_pending_requests(self):
|
|
|
"""Tests if the top-of-stack generator has pending requests."""
|
|
|
- _, _, finished_requests, _, _ = self.generator_stack[-1]
|
|
|
- return not finished_requests
|
|
|
+ return not self.generator_stack[-1].finished_requests
|
|
|
|
|
|
def push_generator(self, gen):
|
|
|
"""Pushes a new generator onto the stack."""
|
|
|
- self.generator_stack.append((gen, None, True, [], False))
|
|
|
+ self.generator_stack.append(GeneratorStackEntry(gen))
|
|
|
# print('Pushed generator %s. Generator count: %d' % (gen, len(self.generator_stack)))
|
|
|
|
|
|
def pop_generator(self):
|
|
@@ -113,30 +141,16 @@ class RequestHandler(object):
|
|
|
|
|
|
def append_reply(self, new_reply):
|
|
|
"""Appends a reply to the top-of-stack generator's list of pending replies."""
|
|
|
- current_generator, requests, requests_done, replies, has_reply = self.generator_stack[-1]
|
|
|
- replies.append(new_reply)
|
|
|
- has_reply = True
|
|
|
- self.generator_stack[-1] = (current_generator, requests, requests_done, replies, has_reply)
|
|
|
+ self.generator_stack[-1].append_reply(new_reply)
|
|
|
|
|
|
def extend_replies(self, new_replies):
|
|
|
"""Appends a list of replies to the top-of-stack generator's list of pending replies."""
|
|
|
- current_generator, requests, requests_done, replies, has_reply = self.generator_stack[-1]
|
|
|
- if new_replies is not None:
|
|
|
- replies.extend(new_replies)
|
|
|
- has_reply = True
|
|
|
- self.generator_stack[-1] = (
|
|
|
- current_generator, requests, requests_done, replies, has_reply)
|
|
|
+ self.generator_stack[-1].extend_replies(new_replies)
|
|
|
|
|
|
def step(self):
|
|
|
"""Performs a single step: accumulated replies are fed to the generator,
|
|
|
which then produces requests."""
|
|
|
- current_generator, _, _, replies, has_reply = self.generator_stack[-1]
|
|
|
-
|
|
|
- # Send the replies to the generator, and ask for new requests.
|
|
|
- requests = current_generator.send(replies if has_reply else None)
|
|
|
-
|
|
|
- # Update the entry on the stack.
|
|
|
- self.generator_stack[-1] = (current_generator, requests, False, [], False)
|
|
|
+ self.generator_stack[-1].step()
|
|
|
|
|
|
def handle_exception(self, exception):
|
|
|
"""Handles the given exception. A Boolean is returned that tells if
|
|
@@ -158,12 +172,11 @@ class RequestHandler(object):
|
|
|
# a single 'TAIL_CALL_ARGS' request. The next iteration will replace
|
|
|
# the dummy frame by an actual frame.
|
|
|
del self.generator_stack[stack_index:]
|
|
|
- self.generator_stack.append(
|
|
|
- (None,
|
|
|
- [('TAIL_CALL_ARGS', [applicable_handler, (exception,)])],
|
|
|
- False,
|
|
|
- [],
|
|
|
- False))
|
|
|
+ stack_entry = GeneratorStackEntry(None)
|
|
|
+ stack_entry.pending_requests = [
|
|
|
+ ('TAIL_CALL_ARGS', [applicable_handler, (exception,)])]
|
|
|
+ stack_entry.finished_requests = False
|
|
|
+ self.generator_stack.append(stack_entry)
|
|
|
return True
|
|
|
|
|
|
# We couldn't find an applicable exception handler, even after exhausting the
|
|
@@ -179,7 +192,7 @@ class RequestHandler(object):
|
|
|
|
|
|
A list of requests and a Boolean are returned. The latter is True
|
|
|
if there are no more requests to process, and false otherwise."""
|
|
|
- _, requests, _, _, _ = self.generator_stack[-1]
|
|
|
+ requests = self.generator_stack[-1].pending_requests
|
|
|
if requests is None or len(requests) == 0:
|
|
|
# Couldn't find a request for the state to handle.
|
|
|
self.set_finished_requests_flag()
|