|
@@ -0,0 +1,130 @@
|
|
|
+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):
|