Browse Source

Add draft of binding code to start up matching engine

Yentl Van Tendeloo 6 years ago
parent
commit
908eeead95
1 changed files with 130 additions and 0 deletions
  1. 130 0
      kernel/modelverse_kernel/main_autogen.py

+ 130 - 0
kernel/modelverse_kernel/main_autogen.py

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