123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- include "primitives.alh"
- include "modelling.alh"
- include "object_operations.alh"
- include "random.alh"
- include "utils.alh"
- Boolean function main(model : Element):
- String result
- Element nodes
- String node
- Element edges
- String edge
- String new_node
- String source
- String destination
- String name
- Element to_explore
- Element rules
- String rule
- String value
- Element explored
- Element remainder_to_explore
- String attr
- explored = set_create()
- 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"
- // Keep following outgoing edges to find matching nodes
- to_explore = set_create()
- remainder_to_explore = set_create()
- set_add(to_explore, node)
- while (set_len(to_explore) > 0):
- // Still explore more!
- node = set_pop(to_explore)
- source = string_replace(node, "/", "_")
- edges = allOutgoingAssociationInstances(model, node, "Rules/Edge")
- while (set_len(edges) > 0):
- edge = set_pop(edges)
- new_node = readAssociationDestination(model, edge)
- if (value_eq(read_attribute(model, new_node, "match"), True)):
- // Is a match node, so fetch the value on the edge
- name = read_attribute(model, edge, "value")
- destination = string_replace(new_node, "/", "_")
- if (element_eq(name, read_root())):
- 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"
- else:
- set_add(remainder_to_explore, node)
- else:
- if (set_in(explored, destination)):
- // 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"
- // 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"
- else:
- // First visit to this element, so just assign
- result = result + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
- set_add(explored, destination)
- 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
- result = result + destination + "_V, = yield [('RV', [" + destination + "])]\n"
- set_add(to_explore, new_node)
- if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)):
- to_explore = remainder_to_explore
- 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"
- 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 "
- nodes = allAssociationDestinations(model, rule, "Rules/contains")
- while (set_len(nodes) > 0):
- node = set_pop(nodes)
- if (value_eq(read_attribute(model, node, "match"), True)):
- // We should match on this node:
- value = read_attribute(model, node, "value")
- if (bool_and(read_type(model, node) == "Rules/NAC", element_eq(value, read_root()))):
- result = result + " and " + string_replace(node, "/", "_") + " is None "
- else:
- result = result + " and " + string_replace(node, "/", "_") + " is not None "
- if (element_neq(value, read_root())):
- // Got a value, so match that as well
- // But check if it is an action element (first character == !)
- String sign
- if (read_type(model, node) == "Rules/NAC"):
- sign = "!="
- else:
- sign = "=="
- if (string_get(value, 0) == "!"):
- result = result + " and " + string_replace(node, "/", "_") + "_V['value'] " + sign + " '" + string_replace(value, "!", "") + "'"
- else:
- result = result + " and " + string_replace(node, "/", "_") + "_V " + sign + " " + value
- result = result + "):\n"
- result = result + "\t# 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
- // For "match", it is exactly the same as before
- // For "delete" edges, we match using "RD" and "RDE"
- Element create_edges
- Element all_nodes
- log("Matching rule " + rule)
- nodes = allAssociationDestinations(model, rule, "Rules/contains")
- all_nodes = set_overlap(nodes, allInstances(model, "Rules/Match"))
- create_edges = set_create()
- explored = set_create()
- while (set_len(nodes) > 0):
- node = set_pop(nodes)
- if (read_type(model, node) == "Rules/Root"):
- // Found the root of this rule, so start exploring again
-
- // Keep following outgoing edges to find matching nodes
- to_explore = set_create()
- remainder_to_explore = set_create()
- set_add(to_explore, node)
- while (set_len(explored) < set_len(all_nodes)):
- while (set_len(to_explore) > 0):
- // Still explore more!
- node = set_pop(to_explore)
- log("Explore " + node)
- set_add(explored, node)
- source = string_replace(node, "/", "_")
- edges = allOutgoingAssociationInstances(model, node, "Rules/MatchEdge")
- while (set_len(edges) > 0):
- edge = set_pop(edges)
- new_node = readAssociationDestination(model, edge)
- name = read_attribute(model, edge, "value")
- destination = string_replace(new_node, "/", "_")
- if (element_eq(name, read_root())):
- 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"
- set_add(to_explore, new_node)
- else:
- set_add(remainder_to_explore, node)
- continue!
- 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"
- else:
- 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"
- // 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"
- else:
- // First visit to this element, so just assign
- result = result + "\t" + 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
- result = result + "\t" + destination + "_V, = yield [('RV', [" + destination + "])]\n"
- 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"
- if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)):
- to_explore = remainder_to_explore
- remainder_to_explore = set_create()
- // Check for nodes that are unexplored, but seemingly not reachable from the root directly
- Element remaining
- String check_elem
- Boolean found
- if (set_len(explored) < set_len(all_nodes)):
- // Find all unexplored nodes
- remaining = set_difference(all_nodes, explored)
- log("Remain unexplored: " + set_to_string(remaining))
- while (set_len(remaining) > 0):
- check_elem = set_pop(remaining)
- edges = allOutgoingAssociationInstances(model, check_elem, "Rules/MatchEdge")
- found = False
- while (set_len(edges) > 0):
- edge = set_pop(edges)
- new_node = readAssociationDestination(model, edge)
- name = read_attribute(model, edge, "value")
- 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"
- found = True
- // Iterated over all edges, so check how many we found!
- if (found):
- 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"
- elif (read_type(model, node) == "Rules/Create"):
- // A node that we should create: do that already, as otherwise we might have to sort
- String attr
- attr = read_attribute(model, node, "value")
- if (element_eq(attr, read_root())):
- // Create empty node
- result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n"
- else:
- // Create value node
- result = result + "\t" + 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)
- // Now create all the new edges, given that we assume everything to be matched
- while (set_len(create_edges) > 0):
- 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"
- else:
- result = result + "\t" + 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"
- log("Got result:")
- log(result)
- return True!
|