Browse Source

Semi-working automatically generated Modelverse Kernel

Yentl Van Tendeloo 4 years ago
parent
commit
f4c0bac705

+ 1 - 0
bootstrap/bootstrap.py

@@ -19,6 +19,7 @@ def bootstrap():
 
     task_frame = [  "evalstack",
                     "returnvalue",
+                    "symbols",
                     ]
 
     primitives = {  "integer_addition": ["Integer", "Integer", "Integer"],

+ 2 - 0
hybrid_server/classes/mvkcontroller.xml

@@ -27,6 +27,8 @@
             for opt in kernel_opts:
                 if opt == 'legacy-interpreter':
                     self.mvk = LegacyModelverseKernel(self.root)
+                elif opt == 'generated':
+                    self.mvk = GeneratedModelverseKernel(self.root)
                 elif opt == 'interpreter':
                     self.mvk.jit.set_jit_enabled(False)
                 elif opt == 'no-thunks':

+ 1 - 0
hybrid_server/server.xml

@@ -18,6 +18,7 @@
         from modelverse_kernel.primitives import SleepKernel
         from modelverse_kernel.main import ModelverseKernel
         from modelverse_kernel.legacy import ModelverseKernel as LegacyModelverseKernel
+        from modelverse_kernel.generated import ModelverseKernel as GeneratedModelverseKernel
         from modelverse_state.main import ModelverseState
         #from modelverse_state.rdf import ModelverseState
         import modelverse_jit.jit as jit

File diff suppressed because it is too large
+ 1287 - 0
kernel/modelverse_kernel/generated.py


+ 44 - 44
kernel/modelverse_kernel/main_autogen.py

@@ -37,32 +37,32 @@ class ModelverseKernel(object):
     ### 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]
+        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]
+        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
+        parameters['root'] = self.root
+        parameters['task_root'] = task_root
+        parameters['taskname'] = taskname
+        parameters['mvk'] = self
 
         # prim is a generator itself!
         try:
@@ -74,57 +74,57 @@ class ModelverseKernel(object):
                 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!")
+            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)))
+            #    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]),
+        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"]),
+        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]),
+            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"]),
+        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_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])
+        new_value, =        yield [('CNV', [value])]
+        _, _ =              yield [('CD', [old_input, 'value', new_value]),
+                                   ('DE', [link])
                                   ]
-        self.returnvalue = {"id": 100, "value": "success"}
+        self.returnvalue = {'id': 100, 'value': 'success'}
 
     ### Generated rules
     def execute_rule(self, taskname):

+ 1 - 1
kernel/rules/MvK_rules.mvc

@@ -1106,7 +1106,7 @@ Rule Const_N15 {
         value = "'finish'"
     }
     Match N15_6 {
-        value = "!const"
+        value = "!constant"
         match = True
     }
     Match N15_7 {}

+ 1 - 1
kernel/rules/MvK_rules_MM.mvc

@@ -27,4 +27,4 @@ Association Edge : Node (Node, Node) {
 Association CreateEdge : Edge (Node, Node) {}
 Association MatchEdge : Edge (Node, Node) {}
 Association DeleteEdge : MatchEdge (Node, Node) {}
-Association NACEdge : Edge (Node, Node) {}
+Association NACEdge : MatchEdge (Node, Node) {}

+ 180 - 38
kernel/rules/to_python.alc

@@ -23,12 +23,147 @@ Boolean function main(model : Element):
 	String attr
 
 	explored = set_create()
-	result = "root, = yield [('RR', [])]\n"
+	result = ""
+
+	// Add the preamble...
+	result = result + "import modelverse_kernel.primitives as primitive_functions\n"
+	result = result + "import modelverse_kernel.compiled as compiled_functions\n"
+	result = result + "from collections import defaultdict\n"
+	result = result + "import sys\n"
+	result = result + "import time\n"
+	result = result + "\n"
+	result = result + "class ModelverseKernel(object):\n"
+	result = result + "    def __init__(self, root):\n"
+	result = result + "        self.root = root\n"
+	result = result + "        self.primitives = {}\n"
+	result = result + "        self.returnvalue = None\n"
+	result = result + "        self.success = True\n"
+	result = result + "        self.generators = {}\n"
+	result = result + "\n"
+	result = result + "    def execute_yields(self, taskname, operation, params, reply):\n"
+	result = result + "        try:\n"
+	result = result + "            self.success = True\n"
+	result = result + "            self.taskname = taskname\n"
+	result = result + "            if taskname not in self.generators:\n"
+	result = result + "                self.generators[taskname] = {}\n"
+	result = result + "            if operation not in self.generators[taskname]:\n"
+	result = result + "                # Create the generator for the function to execute\n"
+	result = result + "                self.generators[taskname][operation] = getattr(self, operation)(taskname, *params)\n"
+	result = result + "\n"
+	result = result + "            if reply is not None:\n"
+	result = result + "                return self.generators[taskname][operation].send(reply)\n"
+	result = result + "            else:\n"
+	result = result + "                return self.generators[taskname][operation].next()\n"
+	result = result + "        except StopIteration:\n"
+	result = result + "            # Done, so remove the generator\n"
+	result = result + "            del self.generators[taskname][operation]\n"
+	result = result + "            return None\n"
+	result = result + "        except:\n"
+	result = result + "            raise\n"
+	result = result + "\n"
+	result = result + "    ##########################\n"
+	result = result + "    ### Process primitives ###\n"
+	result = result + "    ##########################\n"
+	result = result + "    def load_primitives(self, taskname):\n"
+	result = result + "        hierarchy, =     yield [('RD', [self.root, '__hierarchy'])]\n"
+	result = result + "        primitives, =    yield [('RD', [hierarchy, 'primitives'])]\n"
+	result = result + "        keys, =          yield [('RDK', [primitives])]\n"
+	result = result + "        function_names = yield [('RV', [f]) for f in keys]\n"
+	result = result + "        signatures  =    yield [('RDN', [primitives, f]) for f in keys]\n"
+	result = result + "        bodies =         yield [('RD', [f, 'body']) for f in signatures]\n"
+	result = result + "        for i in range(len(keys)):\n"
+	result = result + "            self.primitives[bodies[i]] = getattr(primitive_functions, function_names[i])\n"
+	result = result + "\n"
+	result = result + "    def execute_primitive(self, task_root, inst, taskname):\n"
+	result = result + "        # execute_primitive\n"
+	result = result + "        task_frame, =    yield [('RD', [task_root, 'frame'])]\n"
+	result = result + "        symbols, =       yield [('RD', [task_frame, 'symbols'])]\n"
+	result = result + "        all_links, =     yield [('RO', [symbols])]\n"
+	result = result + "        containers =    yield [('RE', [v]) for v in all_links]\n"
+	result = result + "        outgoings =     yield [('RO', [v]) for v in all_links]\n"
+	result = result + "        dict_values =   yield [('RD', [v[1], 'value']) for v in containers]\n"
+	result = result + "        formals_1 =     yield [('RE', [v[0]]) for v in outgoings]\n"
+	result = result + "        dict_keys_ref = yield [('RD', [v[1], 'name']) for v in formals_1]\n"
+	result = result + "        dict_keys =     yield [('RV', [v]) for v in dict_keys_ref]\n"
+	result = result + "        parameters = dict(zip(dict_keys, dict_values))\n"
+	result = result + "\n"
+	result = result + "        parameters['root'] = self.root\n"
+	result = result + "        parameters['task_root'] = task_root\n"
+	result = result + "        parameters['taskname'] = taskname\n"
+	result = result + "        parameters['mvk'] = self\n"
+	result = result + "\n"
+	result = result + "        # prim is a generator itself!\n"
+	result = result + "        try:\n"
+	result = result + "            # Forward the message we get to this generator\n"
+	result = result + "            # 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)\n"
+	result = result + "            prim = self.primitives[inst](**parameters)\n"
+	result = result + "            inp = None\n"
+	result = result + "            while 1:\n"
+	result = result + "                inp = yield prim.send(inp)\n"
+	result = result + "        except StopIteration:\n"
+	result = result + "            # Execution has ended without return value, so we have no idea what to do\n"
+	result = result + "            raise Exception('Primitive finished without returning a value!')\n"
+	result = result + "        except primitive_functions.PrimitiveFinished as e:\n"
+	result = result + "            # Execution has ended with a returnvalue, so read it out from the exception being thrown\n"
+	result = result + "            result = e.result\n"
+	result = result + "\n"
+	result = result + "            #if result is None:\n"
+	result = result + "            #    raise Exception('Primitive raised exception: value of None for operation %s with parameters %s' % (self.compiled[inst], str(parameters)))\n"
+	result = result + "\n"
+	result = result + "        # Clean up the current stack, as if a return happened\n"
+	result = result + "        old_frame, =    yield [('RD', [task_frame, 'prev'])]\n"
+	result = result + "        lnk, =          yield [('RDE', [old_frame, 'returnvalue'])]\n"
+	result = result + "        _, _, _, _ =    yield [('CD', [old_frame, 'returnvalue', result]),\n"
+	result = result + "                               ('CD', [task_root, 'frame', old_frame]),\n"
+	result = result + "                               ('DE', [lnk]),\n"
+	result = result + "                               ('DN', [task_frame]),\n"
+	result = result + "                              ]\n"
+	result = result + "\n"
+	result = result + "    ########################################\n"
+	result = result + "    ### Execute input and output methods ###\n"
+	result = result + "    ########################################\n"
+	result = result + "    def get_output(self, taskname):\n"
+	result = result + "        task_root, =        yield [('RD', [self.root, taskname])]\n"
+	result = result + "        first_output, =     yield [('RD', [task_root, 'output'])]\n"
+	result = result + "        next_output, rv =   yield [('RD', [first_output, 'next']),\n"
+	result = result + "                                   ('RD', [first_output, 'value']),\n"
+	result = result + "                                  ]\n"
+	result = result + "        if next_output is None:\n"
+	result = result + "            self.success = False\n"
+	result = result + "            self.returnvalue = None\n"
+	result = result + "        else:\n"
+	result = result + "            rv_value, =     yield [('RV', [rv])]\n"
+	result = result + "            _, _ =          yield [('CD', [task_root, 'output', next_output]),\n"
+	result = result + "                                   ('DN', [first_output]),\n"
+	result = result + "                                  ]\n"
+	result = result + "            self.returnvalue = rv_value\n"
+	result = result + "\n"
+	result = result + "    def set_input(self, taskname, value):\n"
+	result = result + "        task_root, =        yield [('RD', [self.root, taskname])]\n"
+	result = result + "        old_input, link =   yield [('RD', [task_root, 'last_input']),\n"
+	result = result + "                                   ('RDE', [task_root, 'last_input']),\n"
+	result = result + "                                  ]\n"
+	result = result + "        new_input, =        yield [('CN', [])]\n"
+	result = result + "        _, _ =              yield [('CD', [task_root, 'last_input', new_input]),\n"
+	result = result + "                                   ('CD', [old_input, 'next', new_input]),\n"
+	result = result + "                                  ]\n"
+	result = result + "\n"
+	result = result + "        new_value, =        yield [('CNV', [value])]\n"
+	result = result + "        _, _ =              yield [('CD', [old_input, 'value', new_value]),\n"
+	result = result + "                                   ('DE', [link])\n"
+	result = result + "                                  ]\n"
+	result = result + "        self.returnvalue = {'id': 100, 'value': 'success'}\n"
+	result = result + "\n"
+	result = result + "    ### Generated rules\n"
+	result = result + "    def execute_rule(self, taskname):\n"
+
+	// Done, now generate the variable code
+	result = result + "        root, = yield [('RR', [])]\n"
 	nodes = allInstances(model, "Rules/Root")
 	while (set_len(nodes) > 0):
 		node = set_pop(nodes)
 		source = string_replace(node, "/", "_")
-		result = result + source + " = root\n"
+		result = result + "        " + source + " = root\n"
 
 		// Keep following outgoing edges to find matching nodes
 		to_explore = set_create()
@@ -40,7 +175,7 @@ Boolean function main(model : Element):
 			node = set_pop(to_explore)
 			source = string_replace(node, "/", "_")
 
-			edges = allOutgoingAssociationInstances(model, node, "Rules/Edge")
+			edges = allOutgoingAssociationInstances(model, node, "Rules/MatchEdge")
 			while (set_len(edges) > 0):
 				edge = set_pop(edges)
 				new_node = readAssociationDestination(model, edge)
@@ -53,7 +188,7 @@ Boolean function main(model : Element):
 						String node_key
 						node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_")
 						if (set_in(explored, node_key)):
-							result = result + destination + ", = yield [('RDN', [" + source + ", " + node_key + "])]\n"
+							result = result + "        " + destination + ", = yield [('RDN', [" + source + ", " + node_key + "])]\n"
 						else:
 							set_add(remainder_to_explore, node)
 					else:
@@ -61,13 +196,13 @@ Boolean function main(model : Element):
 							// Already visited this one in another way, so try to merge!
 							String rand
 							rand = random_string(10)
-							result = result + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
-							result = result + "if " + rand + " != " + destination + ":\n"
+							result = result + "        " + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
+							result = result + "        " + "if " + rand + " != " + destination + ":\n"
 							// If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None)
-							result = result + "\t" + destination + " = None\n"
+							result = result + "            " + destination + " = None\n"
 						else:
 							// First visit to this element, so just assign
-							result = result + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
+							result = result + "        " + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
 							set_add(explored, destination)
 
 							String value
@@ -75,7 +210,7 @@ Boolean function main(model : Element):
 							if (element_neq(value, read_root())):
 								// Match node has a value we should compare as well!
 								// Read out the value from the Modelverse
-								result = result + destination + "_V, = yield [('RV', [" + destination + "])]\n"
+								result = result + "        " + destination + "_V, = yield [('RV', [" + destination + "])]\n"
 
 							set_add(to_explore, new_node)
 
@@ -84,15 +219,15 @@ Boolean function main(model : Element):
 				remainder_to_explore = set_create()
 
 	rules = allInstances(model, "Rules/Rule")
-	result = result + "if (False):\n"
-	result = result + "\t# here to make code generation nicer...\n"
-	result = result + "\tpass\n"
+	result = result + "        " + "if (False):\n"
+	result = result + "            # here to make code generation nicer...\n"
+	result = result + "            pass\n"
 	while (set_len(rules) > 0):
 		// Check if this rule is applicable
 		rule = set_pop(rules)
 
 		// Fetch all elements with a "match" label and check that they are not None (and possibly, that they have a value)
-		result = result + "elif (True "
+		result = result + "        elif (True "
 		nodes = allAssociationDestinations(model, rule, "Rules/contains")
 		while (set_len(nodes) > 0):
 			node = set_pop(nodes)
@@ -120,7 +255,8 @@ Boolean function main(model : Element):
 						result = result + " and " + string_replace(node, "/", "_") + "_V " + sign + " " + value
 
 		result = result + "):\n"
-		result = result + "\t# Execute rule " + rule + "\n"
+		result = result + "            # Execute rule " + rule + "\n"
+		result = result + "            print('Execute rule " + rule + "')\n"
 
 		// We know all the nodes that we already have (in variable "explored")
 		// Still have to match all "match" and "delete" elements
@@ -170,7 +306,7 @@ Boolean function main(model : Element):
 								String node_key
 								node_key = set_pop(allAssociationDestinations(model, edge, ""))
 								if (set_in(explored, node_key)):
-									result = result + "\t" + destination + ", = yield [('RDN', [" + source + ", " + string_replace(node_key, "/", "_") + "])]\n"
+									result = result + "            " + destination + ", = yield [('RDN', [" + source + ", " + string_replace(node_key, "/", "_") + "])]\n"
 									set_add(to_explore, new_node)
 								else:
 									set_add(remainder_to_explore, node)
@@ -178,37 +314,36 @@ Boolean function main(model : Element):
 
 								if (read_type(model, edge) == "Rules/DeleteEdge"):
 									// Delete edge
-									result = result + "\t" + destination + "_DEL, = yield [('RDNE', [" + source + ", " + string_replace(node_key, "/", "_") + "])]\n"
-									result = result + "\tyield [('DE', [" + destination + "_DEL])]\n"
+									result = result + "            " + destination + "_DEL, = yield [('RDNE', [" + source + ", " + string_replace(node_key, "/", "_") + "])]\n"
+									result = result + "            yield [('DE', [" + destination + "_DEL])]\n"
 							else:
 								if (bool_or(string_get(name, 0) == "'", set_in(assigned, name))):
 									if (set_in(explored, new_node)):
 										// Already visited this one in another way, so try to merge!
 										String rand
 										rand = random_string(10)
-										result = result + "\t" + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
-										result = result + "\t" + "if " + rand + " != " + destination + ":\n"
+										result = result + "            " + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
+										result = result + "            " + "if " + rand + " != " + destination + ":\n"
 										// If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None)
-										result = result + "\t" + "\t" + destination + " = None\n"
+										result = result + "            " + "    " + destination + " = None\n"
 									else:
 										// First visit to this element, so just assign
-										result = result + "\t" + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
+										result = result + "            " + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
 
 										String value
 										value = read_attribute(model, new_node, "value")
 										if (element_neq(value, read_root())):
-											// Match node has a value we should compare as well!
-											// Read out the value from the Modelverse
-											if (bool_and(string_get(value, 0) != "!", string_get(value, 0) != "'")):
-												result = result + "\t" + value + ", = yield [('RV', [" + destination + "])]\n"
+											// Read out the value from the Modelverse, as this can be used later for reading edges
+											if (bool_and(bool_and(string_get(value, 0) != "!", string_get(value, 0) != "'"), bool_and(value != "False", value != "True"))):
+												result = result + "            " + value + ", = yield [('RV', [" + destination + "])]\n"
 												set_add(assigned, value)
 
 										set_add(to_explore, new_node)
 
 									if (read_type(model, edge) == "Rules/DeleteEdge"):
 										// Delete edge
-										result = result + "\t" + destination + "_DEL, = yield [('RDE', [" + source + ", " + name + "])]\n"
-										result = result + "\tyield [('DE', [" + destination + "_DEL])]\n"
+										result = result + "            " + destination + "_DEL, = yield [('RDE', [" + source + ", " + name + "])]\n"
+										result = result + "            yield [('DE', [" + destination + "_DEL])]\n"
 								else:
 									set_add(remainder_to_explore, node)
 
@@ -236,9 +371,9 @@ Boolean function main(model : Element):
 								if (set_in(explored, new_node)):
 									// We already explored this node, so we can do a RRD from this place!
 									if (bool_not(found)):
-										result = result + "\tmatched = []\n"
-									result = result + "\t_tmp, = yield [('RRD', [" + string_replace(new_node, "/", "_") + ", " + name + "])]\n"
-									result = result + "\tmatched.append(_tmp)\n"
+										result = result + "            matched = []\n"
+									result = result + "            _tmp, = yield [('RRD', [" + string_replace(new_node, "/", "_") + ", " + name + "])]\n"
+									result = result + "            matched.append(_tmp)\n"
 									found = True
 
 							// Iterated over all edges, so check how many we found!
@@ -246,7 +381,7 @@ Boolean function main(model : Element):
 								set_add(to_explore, check_elem)
 								set_add(explored, check_elem)
 								// Found at least one match, so we try to find an overlapping node
-								result = result + "\t" + string_replace(check_elem, "/", "_") + " = self.set_overlap(matched)[0]\n"
+								result = result + "            " + string_replace(check_elem, "/", "_") + " = self.set_overlap(matched)[0]\n"
 
 			elif (read_type(model, node) == "Rules/Create"):
 				// A node that we should create: do that already, as otherwise we might have to sort
@@ -254,10 +389,10 @@ Boolean function main(model : Element):
 				attr = read_attribute(model, node, "value")
 				if (element_eq(attr, read_root())):
 					// Create empty node
-					result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n"
+					result = result + "            " + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n"
 				else:
 					// Create value node
-					result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CNV', [" + cast_string(attr) + "])]\n"
+					result = result + "            " + string_replace(node, "/", "_") + ", = yield [('CNV', [" + cast_string(attr) + "])]\n"
 			elif (read_type(model, node) == "Rules/CreateEdge"):
 				// Encounter a create edge, so alreade record this for later
 				set_add(create_edges, node)
@@ -267,14 +402,21 @@ Boolean function main(model : Element):
 			edge = set_pop(create_edges)
 			attr = read_attribute(model, edge, "value")
 			if (element_neq(attr, read_root())):
-				result = result + "\t" + string_replace(edge, "/", "_") + ", = yield [('CD', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + attr + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
+				result = result + "            " + string_replace(edge, "/", "_") + ", = yield [('CD', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + attr + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
 			else:
-				result = result + "\t" + string_replace(edge, "/", "_") + ", = yield [('CE', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
+				result = result + "            " + string_replace(edge, "/", "_") + ", = yield [('CE', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
 
-	result = result + "else:\n"
-	result = result + "\t# no rules were applicable, so idle for some time\n"
-	result = result + "\tpass #TODO\n"
+	result = result + "        else:\n"
+	result = result + "            # no rules were applicable, so idle for some time\n"
+	result = result + "            pass #TODO\n"
+	result = result + "            raise Exception(str(locals()))\n"
 
 	log("Got result:")
 	log(result)
+
+	String file
+	file = instantiate_node(model, "Files/File", "")
+	instantiate_attribute(model, file, "name", "generated_kernel.py")
+	instantiate_attribute(model, file, "content", result)
+
 	return True!

+ 5 - 2
kernel/rules/upload.py

@@ -9,8 +9,11 @@ model_add("formalisms/Files", "formalisms/SimpleClassDiagrams", open("kernel/rul
 model_add("models/MvK_rules", "formalisms/MvK_rules_MM", open("kernel/rules/MvK_rules.mvc", 'r').read())
 transformation_add_AL({"Rules": "formalisms/MvK_rules_MM"}, {"Files": "formalisms/Files"}, "models/to_python", open("kernel/rules/to_python.alc", 'r').read())
 #transformation_add_AL({"Rules": "formalisms/MvK_rules_MM"}, {"Files": "formalisms/Files"}, "models/to_graphviz", open("kernel/rules/to_graphviz.alc", 'r').read())
-#transformation_add_AL({"Files": "formalisms/Files"}, {}, "models/write_files", open("kernel/rules/write_files.alc", 'r').read())
+transformation_add_AL({"Files": "formalisms/Files"}, {}, "models/write_files", open("kernel/rules/write_files.alc", 'r').read())
 
+print("Writing to Python...")
 transformation_execute_AL("models/to_python", {"Rules": "models/MvK_rules"}, {"Files": "models/files"})
+print("Writing to file...")
 #transformation_execute_AL("models/to_graphviz", {"Rules": "models/MvK_rules"}, {"Files": "models/files"})
-#transformation_execute_AL("models/write_files", {"Files": "models/files"}, {})
+transformation_execute_AL("models/write_files", {"Files": "models/files"}, {})
+print("DONE")

+ 49 - 0
scripts/run_auto_modelverse.py

@@ -0,0 +1,49 @@
+import subprocess
+import sys
+import os
+
+# sys.executable to use the same Python interpreter used to invoke this command
+if len(sys.argv) < 2:
+    port = "8001"
+else:
+    port = sys.argv[1]
+
+try:
+    # Compile all SCCD models first
+    os.chdir("wrappers")
+    subprocess.check_call([sys.executable, "-m", "sccd.compiler.sccdc", "-p", "threads", "modelverse_SCCD.xml"])
+
+    os.chdir("../hybrid_server")
+    subprocess.check_call([sys.executable, "-m", "sccd.compiler.sccdc", "-p", "threads", "server.xml"])
+
+    os.chdir("..")
+
+    # Start up all services with auto-detection
+    import glob
+    service_paths = glob.glob("services/*/main.py")
+    services = []
+    for service_path in service_paths:
+        print("[SERVICE] loaded " + service_path)
+        service = subprocess.Popen([sys.executable, service_path, "127.0.0.1:%s" % port])
+        services.append(service)
+
+    os.chdir("hybrid_server")
+    #program_to_execute = [sys.executable, "run_mvk_server.py", port]
+    program_to_execute = [sys.executable, "run_mvk_server.py", port, "--kernel=generated"]
+    server = subprocess.Popen(program_to_execute)
+
+    server.wait()
+
+finally:
+    # Stop the server
+    try:
+        server.terminate()
+    except:
+        pass
+
+    # Terminate all services as well
+    for service in services:
+        try:
+            service.terminate()
+        except:
+            pass

+ 1 - 0
scripts/run_local_modelverse.py

@@ -29,6 +29,7 @@ try:
 
     os.chdir("hybrid_server")
     program_to_execute = [sys.executable, "run_mvk_server.py", port]
+    #program_to_execute = [sys.executable, "run_mvk_server.py", port, "--kernel=generated"]
     server = subprocess.Popen(program_to_execute)
 
     server.wait()

+ 1 - 1
wrappers/modelverse_SCCD.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Mon Nov 27 11:24:44 2017
+Date:   Mon Nov 27 15:23:49 2017
 
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server