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):