compiled.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. from modelverse_kernel.primitives import PrimitiveFinished
  2. import time
  3. def get_superclasses(a, b, **remainder):
  4. if 'value' not in b:
  5. b['value'], = yield [("RV", [b['id']])]
  6. model_dict, tm_dict = yield [("RD", [a['id'], "model"]),
  7. ("RD", [a['id'], "type_mapping"])]
  8. worklist = set([b['value']])
  9. found = set([])
  10. cache_value = {}
  11. while worklist:
  12. name = worklist.pop()
  13. if name in found:
  14. continue
  15. elem, = yield [("RD", [model_dict, name])]
  16. found.add(name)
  17. # Iterate over all outgoing links
  18. outgoing, = yield [("RO", [elem])]
  19. outgoing = set(outgoing)
  20. while (outgoing):
  21. link = outgoing.pop()
  22. # If the link is typed by "Inheritance", we add its destination
  23. link_name_node, = yield [("CALL_ARGS", [reverseKeyLookup, [{'id': model_dict}, {'id': link}]])]
  24. if "value" not in link_name_node:
  25. link_name_node['value'], = yield [("RV", [link_name_node['id']])]
  26. t_edge, = yield [("RD", [tm_dict, link_name_node['value']])]
  27. t_edge, = yield [("RV", [t_edge])]
  28. if t_edge == "Inheritance":
  29. edge, = yield [("RE", [link])]
  30. src, dst = edge
  31. # Look up dst's name and add it
  32. if dst not in cache_value:
  33. dst_name, = yield [("CALL_ARGS", [reverseKeyLookup, [{'id': model_dict}, {'id': dst}]])]
  34. dst_name_value, = yield [("RV", [dst_name])]
  35. cache_value[dst] = dst_name_value
  36. dst_name_value = cache_value[dst]
  37. worklist.add(dst_name_value)
  38. result, = yield [("CN", [])]
  39. yield [("CD", [result, i, result]) for i in found]
  40. raise PrimitiveFinished({'id': result})
  41. def reverseKeyLookupMulti(a, b, **remainder):
  42. if "value" not in b:
  43. b['value'], = yield [("RV", [b['id']])]
  44. edges, result = yield [("RO", [a['id']]), ("CN", [])]
  45. expanded_edges = yield [("RE", [i]) for i in edges]
  46. values = yield [("RV", [i[1]]) for i in expanded_edges]
  47. # Keep results in a local Python set, as we want to bundle as many requests as possible
  48. todo = set()
  49. for i, edge in enumerate(values):
  50. if b['value'] == edge:
  51. todo.add(i)
  52. outgoings = yield [("RO", [edges[i]]) for i in todo]
  53. values = yield [("RE", [outgoing[0]]) for outgoing in outgoings]
  54. edges = yield [("CE", [result, result]) for value in values]
  55. yield [("CE", [edge, value[1]]) for edge, value in zip(edges, values)]
  56. raise PrimitiveFinished({'id': result})
  57. def reverseKeyLookup(a, b, **remainder):
  58. edges_out, edges_in = yield [("RO", [a['id']]), ("RI", [b['id']])]
  59. options = set(edges_out) & set(edges_in)
  60. if options:
  61. # Select one option randomly
  62. edge = options.pop()
  63. out_edges, = yield [("RO", [edge])]
  64. # Select one option randomly
  65. out_edge = out_edges.pop()
  66. e, = yield [("RE", [out_edge])]
  67. raise PrimitiveFinished({'id': e[1]})
  68. else:
  69. raise PrimitiveFinished({'value': ""})
  70. def instantiated_name(a, b, **remainder):
  71. if "value" not in b:
  72. b['value'], = yield [("RV", [b["id"]])]
  73. if "id" not in a:
  74. a['id'], = yield [("CNV", [a['value']])]
  75. if b['value'] == "":
  76. b['value'] = "__" + str(a['id'])
  77. raise PrimitiveFinished(b)
  78. def set_merge(a, b, **remainder):
  79. keys, = yield [("RDK", [b['id']])]
  80. edges = yield [("CE", [a['id'], a['id']]) for key in keys]
  81. _ = yield [("CE", [edge, key]) for edge, key in zip(edges, keys)]
  82. raise PrimitiveFinished(a)
  83. def has_value(a, **remainder):
  84. if "value" not in a:
  85. a['value'], = yield [("RV", [a['id']])]
  86. if a['value'] is None:
  87. raise PrimitiveFinished({'value': False})
  88. else:
  89. raise PrimitiveFinished({'value': True})
  90. def make_reverse_dictionary(a, **remainder):
  91. reverse, = yield [("CN", [])]
  92. key_nodes, = yield [("RDK", [a['id']])]
  93. values = yield [("RDN", [a['id'], i]) for i in key_nodes]
  94. yield [("CD", [reverse, str(v), k]) for k, v in zip(key_nodes, values)]
  95. raise PrimitiveFinished({'id': reverse})
  96. def dict_eq(a, b, **remainder):
  97. key_nodes, = yield [("RDK", [a['id']])]
  98. key_values = yield [("RV", [i]) for i in key_nodes]
  99. values = yield [("RD", [a['id'], i]) for i in key_values]
  100. values = yield [("RV", [i]) for i in values]
  101. a_dict = dict(list(zip(key_values, values)))
  102. key_nodes, = yield [("RDK", [b['id']])]
  103. key_values = yield [("RV", [i]) for i in key_nodes]
  104. values = yield [("RD", [b['id'], i]) for i in key_values]
  105. values = yield [("RV", [i]) for i in values]
  106. b_dict = dict(list(zip(key_values, values)))
  107. result, = yield [("CNV", [a_dict == b_dict])]
  108. raise PrimitiveFinished(result)
  109. def string_substr(a, b, c, **remainder):
  110. if "value" not in a:
  111. a['value'], = yield [("RV", [a['id']])]
  112. if "value" not in b:
  113. b['value'], = yield [("RV", [b['id']])]
  114. if "value" not in c:
  115. c['value'], = yield [("RV", [c['id']])]
  116. try:
  117. new_value = a['value'][b['value']:c['value']]
  118. except:
  119. new_value = ""
  120. raise PrimitiveFinished({'value': new_value})
  121. def integer_gt(a, b, **remainder):
  122. if 'value' not in a:
  123. a['value'], = yield [("RV", [a['id']])]
  124. if 'value' not in b:
  125. b['value'], = yield [("RV", [b['id']])]
  126. raise PrimitiveFinished({'value': a['value'] > b['value']})
  127. def integer_neg(a, **remainder):
  128. if 'value' not in a:
  129. a['value'], = yield [("RV", [a['id']])]
  130. raise PrimitiveFinished({'value': -a['value']})
  131. def float_gt(a, b, **remainder):
  132. if 'value' not in a:
  133. a['value'], = yield [("RV", [a['id']])]
  134. if 'value' not in b:
  135. b['value'], = yield [("RV", [b['id']])]
  136. raise PrimitiveFinished({'value': a['value'] > b['value']})
  137. def float_neg(a, **remainder):
  138. if 'value' not in a:
  139. a['value'], = yield [("RV", [a['id']])]
  140. raise PrimitiveFinished({'value': -a['value']})
  141. def value_neq(a, b, **remainder):
  142. if 'value' not in a:
  143. a['value'], = yield [("RV", [a['id']])]
  144. if 'value' not in b:
  145. b['value'], = yield [("RV", [b['id']])]
  146. raise PrimitiveFinished({'value': a['value'] != b['value']})
  147. def element_neq(a, b, **remainder):
  148. if 'id' not in a or 'id' not in b:
  149. raise PrimitiveFinished({'value': False})
  150. else:
  151. raise PrimitiveFinished({'value': a['id'] != b['id']})
  152. def list_append(a, b, **remainder):
  153. if "id" not in b:
  154. b['id'], = yield [("CNV", [b['value']])]
  155. a_outgoing, = yield [("RO", [a['id']])]
  156. _ = yield [("CD", [a['id'], len(a_outgoing), b['id']])]
  157. raise PrimitiveFinished(a)
  158. def list_read(a, b, **remainder):
  159. if 'value' not in b:
  160. b['value'], = yield [("RV", [b['id']])]
  161. result, = yield [("RD", [a['id'], b['value']])]
  162. if result is None:
  163. raise Exception("List read out of bounds: %s" % b['value'])
  164. raise PrimitiveFinished({'id': result})
  165. def list_len(a, **remainder):
  166. outgoings, = yield [("RO", [a['id']])]
  167. result, = yield [("CNV", [len(outgoings)])]
  168. raise PrimitiveFinished({'id': result})
  169. def dict_add(a, b, c, **remainder):
  170. if 'id' not in b:
  171. b['id'], = yield [("CNV", [b['value']])]
  172. if 'id' not in c:
  173. c['id'], = yield [("CNV", [c['value']])]
  174. new_edge, = yield [("CE", [a['id'], c['id']])]
  175. yield [("CE", [new_edge, b['id']])]
  176. raise PrimitiveFinished(a)
  177. def dict_len(a, **remainder):
  178. outgoings, = yield [("RO", [a['id']])]
  179. raise PrimitiveFinished({'value': len(outgoings)})
  180. def set_add(a, b, **remainder):
  181. if 'value' not in b:
  182. b['value'], = yield [("RV", [b['id']])]
  183. is_in, = yield [("RD", [a['id'], b['value']])]
  184. if not is_in:
  185. _, = yield [("CD", [a['id'], b['value'], a['id']])]
  186. raise PrimitiveFinished(a)
  187. def set_add_node(a, b, **remainder):
  188. if 'id' not in b:
  189. b['id'], = yield [("CNV", [b['value']])]
  190. is_in, = yield [("RDN", [a['id'], b['id']])]
  191. if not is_in:
  192. edge, = yield [("CE", [a['id'], a['id']])]
  193. _, = yield [("CE", [edge, b['id']])]
  194. raise PrimitiveFinished(a)
  195. def set_pop(a, **remainder):
  196. outgoing, = yield [("RO", [a['id']])]
  197. if outgoing:
  198. outgoing = outgoing[0]
  199. new_outgoing, = yield [("RO", [outgoing])]
  200. new_outgoing = new_outgoing[0]
  201. edge, _ = yield [("RE", [new_outgoing]), ("DE", [outgoing])]
  202. raise PrimitiveFinished({'id': edge[1]})
  203. else:
  204. raise Exception("POP from empty set")
  205. print("Pop from empty set!")
  206. raise PrimitiveFinished({'id': remainder["root"]})
  207. def set_create(**remainder):
  208. result, = yield [("CN", [])]
  209. raise PrimitiveFinished({'id': result})
  210. def list_create(**remainder):
  211. result, = yield [("CN", [])]
  212. raise PrimitiveFinished({'id': result})
  213. def dict_create(**remainder):
  214. result, = yield [("CN", [])]
  215. raise PrimitiveFinished({'id': result})
  216. def create_tuple(a, b, **remainder):
  217. if "id" not in a:
  218. a['id'], = yield [("CNV", [a['value']])]
  219. if "id" not in b:
  220. b['id'], = yield [("CNV", [b['value']])]
  221. result, = yield [("CN", [])]
  222. _, _ = yield [("CD", [result, 0, a['id']]),
  223. ("CD", [result, 1, b['id']]),
  224. ]
  225. raise PrimitiveFinished({'id': result})
  226. def set_overlap(a, b, **remainder):
  227. a_keys, b_keys, res = yield [("RDK", [a['id']]), ("RDK", [b['id']]), ("CN", [])]
  228. a_values = yield [("RV", [i]) for i in a_keys]
  229. b_values = yield [("RV", [i]) for i in b_keys]
  230. result = set(a_values) & set(b_values)
  231. yield [("CD", [res, value, res]) for value in result]
  232. raise PrimitiveFinished({'id': res})
  233. def list_pop_final(a, **remainder):
  234. lst, = yield [("RO", [a['id']])]
  235. length = len(lst)
  236. result, result_edge = yield [("RD", [a['id'], length - 1]),
  237. ("RDE", [a['id'], length -1])]
  238. _, = yield [("DE", [result_edge])]
  239. raise PrimitiveFinished({'id': result})
  240. def instantiate_node(a, b, c, **remainder):
  241. if "value" not in c:
  242. c['value'], = yield [("RV", [c['id']])]
  243. if "id" not in b:
  244. b['id'], = yield [("CNV", [b['value']])]
  245. node, dict_entry, typing = \
  246. yield [("CN", []),
  247. ("RD", [a['id'], "model"]),
  248. ("RD", [a['id'], "type_mapping"]),
  249. ]
  250. if c['value'] == "":
  251. name = "__" + str(node)
  252. name_node = {'value': name}
  253. else:
  254. name = c['value']
  255. name_node = c
  256. yield [("CD", [dict_entry, name, node])]
  257. yield [("CD", [typing, name, b['id']])]
  258. raise PrimitiveFinished(name_node)
  259. def list_insert(a, b, c, **remainder):
  260. if "id" not in b:
  261. b["id"], = yield [("CNV", [b['value']])]
  262. if "value" not in c:
  263. c['value'], = yield [("RV", [c['id']])]
  264. a_outgoing, = yield [("RO", [a['id']])]
  265. links = yield [("RD", [a['id'], i]) for i in range(c['value'], len(a_outgoing))] + \
  266. [("RDE", [a['id'], i]) for i in range(c['value'], len(a_outgoing))]
  267. values = links[:len(links) // 2]
  268. edges = links[len(links) // 2:]
  269. yield [("CD", [a['id'], c['value'], b['id']])] + \
  270. [("CD", [a['id'], c['value'] + 1 + index, value]) for index, value in enumerate(values)] + \
  271. [("DE", [i]) for i in edges]
  272. raise PrimitiveFinished(a)
  273. def list_delete(a, b, **remainder):
  274. if "value" not in b:
  275. b['value'], = yield [("RV", [b['id']])]
  276. a_outgoing, = yield [("RO", [a['id']])]
  277. links = yield [("RD", [a['id'], i]) for i in range(b['value'], len(a_outgoing))] + \
  278. [("RDE", [a['id'], i]) for i in range(b['value'], len(a_outgoing))]
  279. values = links[:len(links) // 2]
  280. edges = links[len(links) // 2:]
  281. yield [("CD", [a['id'], b['value'] + index, value]) for index, value in enumerate(values[1:])] + \
  282. [("DE", [i]) for i in edges]
  283. raise PrimitiveFinished(a)