to_python.alc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. include "primitives.alh"
  2. include "modelling.alh"
  3. include "object_operations.alh"
  4. include "random.alh"
  5. include "utils.alh"
  6. Boolean function main(model : Element):
  7. String result
  8. Element nodes
  9. String node
  10. Element edges
  11. String edge
  12. String new_node
  13. String source
  14. String destination
  15. String name
  16. Element to_explore
  17. Element rules
  18. String rule
  19. String value
  20. Element explored
  21. Element remainder_to_explore
  22. String attr
  23. explored = set_create()
  24. result = "root, = yield [('RR', [])]\n"
  25. nodes = allInstances(model, "Rules/Root")
  26. while (set_len(nodes) > 0):
  27. node = set_pop(nodes)
  28. source = string_replace(node, "/", "_")
  29. result = result + source + " = root\n"
  30. // Keep following outgoing edges to find matching nodes
  31. to_explore = set_create()
  32. remainder_to_explore = set_create()
  33. set_add(to_explore, node)
  34. while (set_len(to_explore) > 0):
  35. // Still explore more!
  36. node = set_pop(to_explore)
  37. source = string_replace(node, "/", "_")
  38. edges = allOutgoingAssociationInstances(model, node, "Rules/Edge")
  39. while (set_len(edges) > 0):
  40. edge = set_pop(edges)
  41. new_node = readAssociationDestination(model, edge)
  42. if (value_eq(read_attribute(model, new_node, "match"), True)):
  43. // Is a match node, so fetch the value on the edge
  44. name = read_attribute(model, edge, "value")
  45. destination = string_replace(new_node, "/", "_")
  46. if (element_eq(name, read_root())):
  47. String node_key
  48. node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_")
  49. if (set_in(explored, node_key)):
  50. result = result + destination + ", = yield [('RDN', [" + source + ", " + node_key + "])]\n"
  51. else:
  52. set_add(remainder_to_explore, node)
  53. else:
  54. if (set_in(explored, destination)):
  55. // Already visited this one in another way, so try to merge!
  56. String rand
  57. rand = random_string(10)
  58. result = result + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
  59. result = result + "if " + rand + " != " + destination + ":\n"
  60. // If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None)
  61. result = result + "\t" + destination + " = None\n"
  62. else:
  63. // First visit to this element, so just assign
  64. result = result + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
  65. set_add(explored, destination)
  66. String value
  67. value = read_attribute(model, new_node, "value")
  68. if (element_neq(value, read_root())):
  69. // Match node has a value we should compare as well!
  70. // Read out the value from the Modelverse
  71. result = result + destination + "_V, = yield [('RV', [" + destination + "])]\n"
  72. set_add(to_explore, new_node)
  73. if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)):
  74. to_explore = remainder_to_explore
  75. remainder_to_explore = set_create()
  76. rules = allInstances(model, "Rules/Rule")
  77. while (set_len(rules) > 0):
  78. // Check if this rule is applicable
  79. rule = set_pop(rules)
  80. // Fetch all elements with a "match" label and check that they are not None (and possibly, that they have a value)
  81. result = result + "if (True "
  82. nodes = allAssociationDestinations(model, rule, "Rules/contains")
  83. while (set_len(nodes) > 0):
  84. node = set_pop(nodes)
  85. if (value_eq(read_attribute(model, node, "match"), True)):
  86. // We should match on this node:
  87. value = read_attribute(model, node, "value")
  88. if (bool_and(read_type(model, node) == "Rules/NAC", element_eq(value, read_root()))):
  89. result = result + " and " + string_replace(node, "/", "_") + " is None "
  90. else:
  91. result = result + " and " + string_replace(node, "/", "_") + " is not None "
  92. if (element_neq(value, read_root())):
  93. // Got a value, so match that as well
  94. // But check if it is an action element (first character == !)
  95. String sign
  96. if (read_type(model, node) == "Rules/NAC"):
  97. sign = "!="
  98. else:
  99. sign = "=="
  100. if (string_get(value, 0) == "!"):
  101. result = result + " and " + string_replace(node, "/", "_") + "_V['value'] " + sign + " '" + string_replace(value, "!", "") + "'"
  102. else:
  103. result = result + " and " + string_replace(node, "/", "_") + "_V " + sign + " " + value
  104. result = result + "):\n"
  105. result = result + "\t# Execute rule " + rule + "\n"
  106. // We know all the nodes that we already have (in variable "explored")
  107. // Still have to match all "match" and "delete" elements
  108. // For "match", it is exactly the same as before
  109. // For "delete" edges, we match using "RD" and "RDE"
  110. nodes = allAssociationDestinations(model, rule, "Rules/contains")
  111. Element create_edges
  112. create_edges = set_create()
  113. explored = set_create()
  114. while (set_len(nodes) > 0):
  115. node = set_pop(nodes)
  116. if (read_type(model, node) == "Rules/Root"):
  117. // Found the root of this rule, so start exploring again
  118. // Keep following outgoing edges to find matching nodes
  119. to_explore = set_create()
  120. remainder_to_explore = set_create()
  121. set_add(to_explore, node)
  122. while (set_len(to_explore) > 0):
  123. // Still explore more!
  124. node = set_pop(to_explore)
  125. source = string_replace(node, "/", "_")
  126. edges = allOutgoingAssociationInstances(model, node, "Rules/MatchEdge")
  127. while (set_len(edges) > 0):
  128. edge = set_pop(edges)
  129. new_node = readAssociationDestination(model, edge)
  130. name = read_attribute(model, edge, "value")
  131. destination = string_replace(new_node, "/", "_")
  132. if (element_eq(name, read_root())):
  133. String node_key
  134. node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_")
  135. if (set_in(explored, node_key)):
  136. result = result + "\t" + destination + ", = yield [('RDN', [" + source + ", " + node_key + "])]\n"
  137. else:
  138. set_add(remainder_to_explore, node)
  139. continue!
  140. if (read_type(model, edge) == "Rules/DeleteEdge"):
  141. // Delete edge
  142. result = result + "\t" + destination + "_DEL, = yield [('RDNE', [" + source + ", " + node_key + "])]\n"
  143. result = result + "\tyield [('DE', [" + destination + "_DEL])]\n"
  144. else:
  145. if (set_in(explored, destination)):
  146. // Already visited this one in another way, so try to merge!
  147. String rand
  148. rand = random_string(10)
  149. result = result + "\t" + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
  150. result = result + "\t" + "if " + rand + " != " + destination + ":\n"
  151. // If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None)
  152. result = result + "\t" + "\t" + destination + " = None\n"
  153. else:
  154. // First visit to this element, so just assign
  155. result = result + "\t" + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
  156. set_add(explored, destination)
  157. String value
  158. value = read_attribute(model, new_node, "value")
  159. if (element_neq(value, read_root())):
  160. // Match node has a value we should compare as well!
  161. // Read out the value from the Modelverse
  162. result = result + "\t" + destination + "_V, = yield [('RV', [" + destination + "])]\n"
  163. set_add(to_explore, new_node)
  164. if (read_type(model, edge) == "Rules/DeleteEdge"):
  165. // Delete edge
  166. result = result + "\t" + destination + "_DEL, = yield [('RDE', [" + source + ", " + name + "])]\n"
  167. result = result + "\tyield [('DE', [" + destination + "_DEL])]\n"
  168. if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)):
  169. to_explore = remainder_to_explore
  170. remainder_to_explore = set_create()
  171. elif (read_type(model, node) == "Rules/Create"):
  172. // A node that we should create: do that already, as otherwise we might have to sort
  173. String attr
  174. attr = read_attribute(model, node, "value")
  175. if (element_eq(attr, read_root())):
  176. // Create empty node
  177. result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n"
  178. else:
  179. // Create value node
  180. result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CNV', [" + cast_string(attr) + "])]\n"
  181. elif (read_type(model, node) == "Rules/CreateEdge"):
  182. // Encounter a create edge, so alreade record this for later
  183. set_add(create_edges, node)
  184. // Now create all the new edges, given that we assume everything to be matched
  185. while (set_len(create_edges) > 0):
  186. edge = set_pop(create_edges)
  187. attr = read_attribute(model, edge, "value")
  188. if (element_neq(attr, read_root())):
  189. result = result + "\t" + string_replace(edge, "/", "_") + ", = yield [('CD', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + attr + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
  190. else:
  191. result = result + "\t" + string_replace(edge, "/", "_") + ", = yield [('CE', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
  192. log("Got result:")
  193. log(result)
  194. return True!