Browse Source

Semi-working automatically generated Modelverse Kernel

Yentl Van Tendeloo 8 years ago
parent
commit
f4c0bac705

+ 1 - 0
bootstrap/bootstrap.py

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

+ 2 - 0
hybrid_server/classes/mvkcontroller.xml

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

+ 1 - 0
hybrid_server/server.xml

@@ -18,6 +18,7 @@
         from modelverse_kernel.primitives import SleepKernel
         from modelverse_kernel.primitives import SleepKernel
         from modelverse_kernel.main import ModelverseKernel
         from modelverse_kernel.main import ModelverseKernel
         from modelverse_kernel.legacy import ModelverseKernel as LegacyModelverseKernel
         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.main import ModelverseState
         #from modelverse_state.rdf import ModelverseState
         #from modelverse_state.rdf import ModelverseState
         import modelverse_jit.jit as jit
         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 ###
     ### Process primitives ###
     ##########################
     ##########################
     def load_primitives(self, taskname):
     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)):
         for i in range(len(keys)):
             self.primitives[bodies[i]] = getattr(primitive_functions, function_names[i])
             self.primitives[bodies[i]] = getattr(primitive_functions, function_names[i])
 
 
     def execute_primitive(self, task_root, inst, taskname):
     def execute_primitive(self, task_root, inst, taskname):
         # execute_primitive
         # 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 = 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!
         # prim is a generator itself!
         try:
         try:
@@ -74,57 +74,57 @@ class ModelverseKernel(object):
                 inp = yield prim.send(inp)
                 inp = yield prim.send(inp)
         except StopIteration:
         except StopIteration:
             # Execution has ended without return value, so we have no idea what to do
             # 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:
         except primitive_functions.PrimitiveFinished as e:
             # Execution has ended with a returnvalue, so read it out from the exception being thrown
             # Execution has ended with a returnvalue, so read it out from the exception being thrown
             result = e.result
             result = e.result
 
 
             #if result is None:
             #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
         # 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 ###
     ### Execute input and output methods ###
     ########################################
     ########################################
     def get_output(self, taskname):
     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:
         if next_output is None:
             self.success = False
             self.success = False
             self.returnvalue = None
             self.returnvalue = None
         else:
         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
             self.returnvalue = rv_value
 
 
     def set_input(self, taskname, 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
     ### Generated rules
     def execute_rule(self, taskname):
     def execute_rule(self, taskname):

+ 1 - 1
kernel/rules/MvK_rules.mvc

@@ -1106,7 +1106,7 @@ Rule Const_N15 {
         value = "'finish'"
         value = "'finish'"
     }
     }
     Match N15_6 {
     Match N15_6 {
-        value = "!const"
+        value = "!constant"
         match = True
         match = True
     }
     }
     Match N15_7 {}
     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 CreateEdge : Edge (Node, Node) {}
 Association MatchEdge : Edge (Node, Node) {}
 Association MatchEdge : Edge (Node, Node) {}
 Association DeleteEdge : MatchEdge (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
 	String attr
 
 
 	explored = set_create()
 	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")
 	nodes = allInstances(model, "Rules/Root")
 	while (set_len(nodes) > 0):
 	while (set_len(nodes) > 0):
 		node = set_pop(nodes)
 		node = set_pop(nodes)
 		source = string_replace(node, "/", "_")
 		source = string_replace(node, "/", "_")
-		result = result + source + " = root\n"
+		result = result + "        " + source + " = root\n"
 
 
 		// Keep following outgoing edges to find matching nodes
 		// Keep following outgoing edges to find matching nodes
 		to_explore = set_create()
 		to_explore = set_create()
@@ -40,7 +175,7 @@ Boolean function main(model : Element):
 			node = set_pop(to_explore)
 			node = set_pop(to_explore)
 			source = string_replace(node, "/", "_")
 			source = string_replace(node, "/", "_")
 
 
-			edges = allOutgoingAssociationInstances(model, node, "Rules/Edge")
+			edges = allOutgoingAssociationInstances(model, node, "Rules/MatchEdge")
 			while (set_len(edges) > 0):
 			while (set_len(edges) > 0):
 				edge = set_pop(edges)
 				edge = set_pop(edges)
 				new_node = readAssociationDestination(model, edge)
 				new_node = readAssociationDestination(model, edge)
@@ -53,7 +188,7 @@ Boolean function main(model : Element):
 						String node_key
 						String node_key
 						node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_")
 						node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_")
 						if (set_in(explored, node_key)):
 						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:
 						else:
 							set_add(remainder_to_explore, node)
 							set_add(remainder_to_explore, node)
 					else:
 					else:
@@ -61,13 +196,13 @@ Boolean function main(model : Element):
 							// Already visited this one in another way, so try to merge!
 							// Already visited this one in another way, so try to merge!
 							String rand
 							String rand
 							rand = random_string(10)
 							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)
 							// 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:
 						else:
 							// First visit to this element, so just assign
 							// 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)
 							set_add(explored, destination)
 
 
 							String value
 							String value
@@ -75,7 +210,7 @@ Boolean function main(model : Element):
 							if (element_neq(value, read_root())):
 							if (element_neq(value, read_root())):
 								// Match node has a value we should compare as well!
 								// Match node has a value we should compare as well!
 								// Read out the value from the Modelverse
 								// 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)
 							set_add(to_explore, new_node)
 
 
@@ -84,15 +219,15 @@ Boolean function main(model : Element):
 				remainder_to_explore = set_create()
 				remainder_to_explore = set_create()
 
 
 	rules = allInstances(model, "Rules/Rule")
 	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):
 	while (set_len(rules) > 0):
 		// Check if this rule is applicable
 		// Check if this rule is applicable
 		rule = set_pop(rules)
 		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)
 		// 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")
 		nodes = allAssociationDestinations(model, rule, "Rules/contains")
 		while (set_len(nodes) > 0):
 		while (set_len(nodes) > 0):
 			node = set_pop(nodes)
 			node = set_pop(nodes)
@@ -120,7 +255,8 @@ Boolean function main(model : Element):
 						result = result + " and " + string_replace(node, "/", "_") + "_V " + sign + " " + value
 						result = result + " and " + string_replace(node, "/", "_") + "_V " + sign + " " + value
 
 
 		result = result + "):\n"
 		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")
 		// We know all the nodes that we already have (in variable "explored")
 		// Still have to match all "match" and "delete" elements
 		// Still have to match all "match" and "delete" elements
@@ -170,7 +306,7 @@ Boolean function main(model : Element):
 								String node_key
 								String node_key
 								node_key = set_pop(allAssociationDestinations(model, edge, ""))
 								node_key = set_pop(allAssociationDestinations(model, edge, ""))
 								if (set_in(explored, node_key)):
 								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)
 									set_add(to_explore, new_node)
 								else:
 								else:
 									set_add(remainder_to_explore, node)
 									set_add(remainder_to_explore, node)
@@ -178,37 +314,36 @@ Boolean function main(model : Element):
 
 
 								if (read_type(model, edge) == "Rules/DeleteEdge"):
 								if (read_type(model, edge) == "Rules/DeleteEdge"):
 									// Delete edge
 									// 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:
 							else:
 								if (bool_or(string_get(name, 0) == "'", set_in(assigned, name))):
 								if (bool_or(string_get(name, 0) == "'", set_in(assigned, name))):
 									if (set_in(explored, new_node)):
 									if (set_in(explored, new_node)):
 										// Already visited this one in another way, so try to merge!
 										// Already visited this one in another way, so try to merge!
 										String rand
 										String rand
 										rand = random_string(10)
 										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)
 										// 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:
 									else:
 										// First visit to this element, so just assign
 										// 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
 										String value
 										value = read_attribute(model, new_node, "value")
 										value = read_attribute(model, new_node, "value")
 										if (element_neq(value, read_root())):
 										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(assigned, value)
 
 
 										set_add(to_explore, new_node)
 										set_add(to_explore, new_node)
 
 
 									if (read_type(model, edge) == "Rules/DeleteEdge"):
 									if (read_type(model, edge) == "Rules/DeleteEdge"):
 										// Delete edge
 										// 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:
 								else:
 									set_add(remainder_to_explore, node)
 									set_add(remainder_to_explore, node)
 
 
@@ -236,9 +371,9 @@ Boolean function main(model : Element):
 								if (set_in(explored, new_node)):
 								if (set_in(explored, new_node)):
 									// We already explored this node, so we can do a RRD from this place!
 									// We already explored this node, so we can do a RRD from this place!
 									if (bool_not(found)):
 									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
 									found = True
 
 
 							// Iterated over all edges, so check how many we found!
 							// 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(to_explore, check_elem)
 								set_add(explored, check_elem)
 								set_add(explored, check_elem)
 								// Found at least one match, so we try to find an overlapping node
 								// 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"):
 			elif (read_type(model, node) == "Rules/Create"):
 				// A node that we should create: do that already, as otherwise we might have to sort
 				// 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")
 				attr = read_attribute(model, node, "value")
 				if (element_eq(attr, read_root())):
 				if (element_eq(attr, read_root())):
 					// Create empty node
 					// Create empty node
-					result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n"
+					result = result + "            " + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n"
 				else:
 				else:
 					// Create value node
 					// 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"):
 			elif (read_type(model, node) == "Rules/CreateEdge"):
 				// Encounter a create edge, so alreade record this for later
 				// Encounter a create edge, so alreade record this for later
 				set_add(create_edges, node)
 				set_add(create_edges, node)
@@ -267,14 +402,21 @@ Boolean function main(model : Element):
 			edge = set_pop(create_edges)
 			edge = set_pop(create_edges)
 			attr = read_attribute(model, edge, "value")
 			attr = read_attribute(model, edge, "value")
 			if (element_neq(attr, read_root())):
 			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:
 			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("Got result:")
 	log(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!
 	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())
 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_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({"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"})
 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/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")
     os.chdir("hybrid_server")
     program_to_execute = [sys.executable, "run_mvk_server.py", port]
     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 = subprocess.Popen(program_to_execute)
 
 
     server.wait()
     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)
 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 author: Yentl Van Tendeloo
 Model name:   MvK Server
 Model name:   MvK Server