compiled.py 14 KB

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