to_python.alc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. result = result + "if (False):\n"
  78. result = result + "\t# here to make code generation nicer...\n"
  79. result = result + "\tpass\n"
  80. while (set_len(rules) > 0):
  81. // Check if this rule is applicable
  82. rule = set_pop(rules)
  83. // Fetch all elements with a "match" label and check that they are not None (and possibly, that they have a value)
  84. result = result + "elif (True "
  85. nodes = allAssociationDestinations(model, rule, "Rules/contains")
  86. while (set_len(nodes) > 0):
  87. node = set_pop(nodes)
  88. if (value_eq(read_attribute(model, node, "match"), True)):
  89. // We should match on this node:
  90. value = read_attribute(model, node, "value")
  91. if (bool_and(read_type(model, node) == "Rules/NAC", element_eq(value, read_root()))):
  92. result = result + " and " + string_replace(node, "/", "_") + " is None "
  93. else:
  94. result = result + " and " + string_replace(node, "/", "_") + " is not None "
  95. if (element_neq(value, read_root())):
  96. // Got a value, so match that as well
  97. // But check if it is an action element (first character == !)
  98. String sign
  99. if (read_type(model, node) == "Rules/NAC"):
  100. sign = "!="
  101. else:
  102. sign = "=="
  103. if (string_get(value, 0) == "!"):
  104. result = result + " and " + string_replace(node, "/", "_") + "_V['value'] " + sign + " '" + string_replace(value, "!", "") + "'"
  105. else:
  106. result = result + " and " + string_replace(node, "/", "_") + "_V " + sign + " " + value
  107. result = result + "):\n"
  108. result = result + "\t# Execute rule " + rule + "\n"
  109. // We know all the nodes that we already have (in variable "explored")
  110. // Still have to match all "match" and "delete" elements
  111. // For "match", it is exactly the same as before
  112. // For "delete" edges, we match using "RD" and "RDE"
  113. nodes = allAssociationDestinations(model, rule, "Rules/contains")
  114. Element create_edges
  115. create_edges = set_create()
  116. explored = set_create()
  117. while (set_len(nodes) > 0):
  118. node = set_pop(nodes)
  119. if (read_type(model, node) == "Rules/Root"):
  120. // Found the root of this rule, so start exploring again
  121. // Keep following outgoing edges to find matching nodes
  122. to_explore = set_create()
  123. remainder_to_explore = set_create()
  124. set_add(to_explore, node)
  125. while (set_len(to_explore) > 0):
  126. // Still explore more!
  127. node = set_pop(to_explore)
  128. source = string_replace(node, "/", "_")
  129. edges = allOutgoingAssociationInstances(model, node, "Rules/MatchEdge")
  130. while (set_len(edges) > 0):
  131. edge = set_pop(edges)
  132. new_node = readAssociationDestination(model, edge)
  133. name = read_attribute(model, edge, "value")
  134. destination = string_replace(new_node, "/", "_")
  135. if (element_eq(name, read_root())):
  136. String node_key
  137. node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_")
  138. if (set_in(explored, node_key)):
  139. result = result + "\t" + destination + ", = yield [('RDN', [" + source + ", " + node_key + "])]\n"
  140. else:
  141. set_add(remainder_to_explore, node)
  142. continue!
  143. if (read_type(model, edge) == "Rules/DeleteEdge"):
  144. // Delete edge
  145. result = result + "\t" + destination + "_DEL, = yield [('RDNE', [" + source + ", " + node_key + "])]\n"
  146. result = result + "\tyield [('DE', [" + destination + "_DEL])]\n"
  147. else:
  148. if (set_in(explored, destination)):
  149. // Already visited this one in another way, so try to merge!
  150. String rand
  151. rand = random_string(10)
  152. result = result + "\t" + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
  153. result = result + "\t" + "if " + rand + " != " + destination + ":\n"
  154. // If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None)
  155. result = result + "\t" + "\t" + destination + " = None\n"
  156. else:
  157. // First visit to this element, so just assign
  158. result = result + "\t" + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
  159. set_add(explored, destination)
  160. String value
  161. value = read_attribute(model, new_node, "value")
  162. if (element_neq(value, read_root())):
  163. // Match node has a value we should compare as well!
  164. // Read out the value from the Modelverse
  165. result = result + "\t" + destination + "_V, = yield [('RV', [" + destination + "])]\n"
  166. set_add(to_explore, new_node)
  167. if (read_type(model, edge) == "Rules/DeleteEdge"):
  168. // Delete edge
  169. result = result + "\t" + destination + "_DEL, = yield [('RDE', [" + source + ", " + name + "])]\n"
  170. result = result + "\tyield [('DE', [" + destination + "_DEL])]\n"
  171. if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)):
  172. to_explore = remainder_to_explore
  173. remainder_to_explore = set_create()
  174. elif (read_type(model, node) == "Rules/Create"):
  175. // A node that we should create: do that already, as otherwise we might have to sort
  176. String attr
  177. attr = read_attribute(model, node, "value")
  178. if (element_eq(attr, read_root())):
  179. // Create empty node
  180. result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n"
  181. else:
  182. // Create value node
  183. result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CNV', [" + cast_string(attr) + "])]\n"
  184. elif (read_type(model, node) == "Rules/CreateEdge"):
  185. // Encounter a create edge, so alreade record this for later
  186. set_add(create_edges, node)
  187. // Now create all the new edges, given that we assume everything to be matched
  188. while (set_len(create_edges) > 0):
  189. edge = set_pop(create_edges)
  190. attr = read_attribute(model, edge, "value")
  191. if (element_neq(attr, read_root())):
  192. result = result + "\t" + string_replace(edge, "/", "_") + ", = yield [('CD', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + attr + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
  193. else:
  194. result = result + "\t" + string_replace(edge, "/", "_") + ", = yield [('CE', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
  195. result = result + "else:\n"
  196. result = result + "\t# no rules were applicable, so idle for some time\n"
  197. result = result + "\tTODO
  198. log("Got result:")
  199. log(result)
  200. return True!