import modelverse_kernel.primitives as primitive_functions import modelverse_kernel.compiled as compiled_functions from collections import defaultdict import sys import time class ModelverseKernel(object): def __init__(self, root): self.root = root self.primitives = {} self.returnvalue = None self.success = True self.generators = {} def execute_yields(self, taskname, operation, params, reply): try: self.success = True self.taskname = taskname if taskname not in self.generators: self.generators[taskname] = {} if operation not in self.generators[taskname]: # Create the generator for the function to execute self.generators[taskname][operation] = getattr(self, operation)(taskname, *params) if reply is not None: return self.generators[taskname][operation].send(reply) else: return self.generators[taskname][operation].next() except StopIteration: # Done, so remove the generator del self.generators[taskname][operation] return None except: raise ########################## ### Process primitives ### ########################## def load_primitives(self, taskname): hierarchy, = yield [('RD', [self.root, '__hierarchy'])] primitives, = yield [('RD', [hierarchy, 'primitives'])] keys, = yield [('RDK', [primitives])] function_names = yield [('RV', [f]) for f in keys] signatures = yield [('RDN', [primitives, f]) for f in keys] bodies = yield [('RD', [f, 'body']) for f in signatures] for i in range(len(keys)): self.primitives[bodies[i]] = getattr(primitive_functions, function_names[i]) def execute_primitive(self, task_root, inst, taskname): # execute_primitive task_frame, = yield [('RD', [task_root, 'frame'])] symbols, = yield [('RD', [task_frame, 'symbols'])] all_links, = yield [('RO', [symbols])] containers = yield [('RE', [v]) for v in all_links] outgoings = yield [('RO', [v]) for v in all_links] dict_values = yield [('RD', [v[1], 'value']) for v in containers] formals_1 = yield [('RE', [v[0]]) for v in outgoings] dict_keys_ref = yield [('RD', [v[1], 'name']) for v in formals_1] dict_keys = yield [('RV', [v]) for v in dict_keys_ref] parameters = dict(zip(dict_keys, dict_values)) parameters['root'] = self.root parameters['task_root'] = task_root parameters['taskname'] = taskname parameters['mvk'] = self # prim is a generator itself! try: # Forward the message we get to this generator # Sometimes it might not even be a generator, in which case this should already be in the except block (i.e., for the Read Root operation) prim = self.primitives[inst](**parameters) inp = None while 1: inp = yield prim.send(inp) except StopIteration: # Execution has ended without return value, so we have no idea what to do raise Exception('Primitive finished without returning a value!') except primitive_functions.PrimitiveFinished as e: # Execution has ended with a returnvalue, so read it out from the exception being thrown result = e.result #if result is None: # raise Exception('Primitive raised exception: value of None for operation %s with parameters %s' % (self.compiled[inst], str(parameters))) # Clean up the current stack, as if a return happened old_frame, = yield [('RD', [task_frame, 'prev'])] lnk, = yield [('RDE', [old_frame, 'returnvalue'])] _, _, _, _ = yield [('CD', [old_frame, 'returnvalue', result]), ('CD', [task_root, 'frame', old_frame]), ('DE', [lnk]), ('DN', [task_frame]), ] ######################################## ### Execute input and output methods ### ######################################## def get_output(self, taskname): task_root, = yield [('RD', [self.root, taskname])] first_output, = yield [('RD', [task_root, 'output'])] next_output, rv = yield [('RD', [first_output, 'next']), ('RD', [first_output, 'value']), ] if next_output is None: self.success = False self.returnvalue = None else: rv_value, = yield [('RV', [rv])] _, _ = yield [('CD', [task_root, 'output', next_output]), ('DN', [first_output]), ] self.returnvalue = rv_value def set_input(self, taskname, value): task_root, = yield [('RD', [self.root, taskname])] old_input, link = yield [('RD', [task_root, 'last_input']), ('RDE', [task_root, 'last_input']), ] new_input, = yield [('CN', [])] _, _ = yield [('CD', [task_root, 'last_input', new_input]), ('CD', [old_input, 'next', new_input]), ] new_value, = yield [('CNV', [value])] _, _ = yield [('CD', [old_input, 'value', new_value]), ('DE', [link]) ] self.returnvalue = {'id': 100, 'value': 'success'} ### Generated rules def execute_rule(self, taskname):