|
@@ -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!
|