compiled.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. from modelverse_kernel.primitives import PrimitiveFinished
  2. import modelverse_jit.runtime as jit_runtime
  3. def reverseKeyLookup(a, b, **remainder):
  4. edges, = yield [("RO", [a])]
  5. expanded_edges = yield [("RE", [i]) for i in edges]
  6. for i, edge in enumerate(expanded_edges):
  7. if b == edge[1]:
  8. # Found our edge: edges[i]
  9. outgoing, = yield [("RO", [edges[i]])]
  10. result, = yield [("RE", [outgoing[0]])]
  11. raise PrimitiveFinished(result[1])
  12. result, = yield [("CNV", ["(unknown: %s)" % b])]
  13. raise PrimitiveFinished(result)
  14. """
  15. def read_attribute(a, b, c, **remainder):
  16. model_dict, b_val, c_val, type_mapping = \
  17. yield [("RD", [a, "model"]),
  18. ("RV", [b]),
  19. ("RV", [c]),
  20. ("RD", [a, "type_mapping"]),
  21. ]
  22. model_instance, = \
  23. yield [("RD", [model_dict, b_val])]
  24. edges, = yield [("RO", [model_instance])]
  25. edge_types = yield [("RDN", [type_mapping, i]) for i in edges]
  26. type_edge_val = yield [("RE", [i]) for i in edge_types]
  27. src_nodes = set([i[0] for i in type_edge_val])
  28. found_edges = yield [("RDE", [i, c_val]) for i in src_nodes]
  29. for e1 in found_edges:
  30. if e1 is not None:
  31. # Found an edge!
  32. for i, e2 in enumerate(edge_types):
  33. if e1 == e2:
  34. # The instance of this edge is the one we want!
  35. edge = edges[i]
  36. edge_val, = yield [("RE", [edge])]
  37. result = edge_val[1]
  38. raise PrimitiveFinished(result)
  39. else:
  40. result, = yield [("RR", [])]
  41. raise PrimitiveFinished(result)
  42. raise Exception("Error in reading edge!")
  43. """
  44. """
  45. def dict_eq(a, b, **remainder):
  46. keys_a, keys_b = yield [("RDK", [a]), ("RDK", [b])]
  47. if len(keys_a) != len(keys_b):
  48. false, = yield [("CNV", [False])]
  49. raise PrimitiveFinished(false)
  50. resolved_names_a = yield [("RV", [i]) for i in keys_a]
  51. resolved_names_b = yield [("RV", [i]) for i in keys_b]
  52. if (set(resolved_names_a) != set(resolved_names_b)):
  53. false, = yield [("CNV", [False])]
  54. raise PrimitiveFinished(false)
  55. values_a = yield [("RD", [a, i]) for i in resolved_names_a]
  56. values_b = yield [("RD", [b, i]) for i in resolved_names_b]
  57. dict_a = dict(zip(resolved_names_a, values_a))
  58. dict_b = dict(zip(resolved_names_b, values_b))
  59. result, = yield [("CNV", [dict_a == dict_b])]
  60. raise PrimitiveFinished(result)
  61. """
  62. def set_copy(a, **remainder):
  63. b, = yield [("CN", [])]
  64. links, = yield [("RO", [a])]
  65. exp_links = yield [("RE", [i]) for i in links]
  66. _ = yield [("CE", [b, i[1]]) for i in exp_links]
  67. raise PrimitiveFinished(b)
  68. """
  69. def allInstances(a, b, **remainder):
  70. b_val, = yield [("RV", [b])]
  71. model_dict,= yield [("RD", [a, "model"])]
  72. metamodel, = yield [("RD", [a, "metamodel"])]
  73. m3, = yield [("RD", [metamodel, "metamodel"])]
  74. m3_model, = yield [("RD", [m3, "model"])]
  75. mm_dict, = yield [("RD", [metamodel, "model"])]
  76. typing, = yield [("RD", [a, "type_mapping"])]
  77. elem_keys, = yield [("RDK", [model_dict])]
  78. elems = yield [("RDN", [model_dict, i]) for i in elem_keys]
  79. mms = yield [("RDN", [typing, i]) for i in elems]
  80. # Have the type for each name
  81. types_to_name_nodes = {}
  82. for key, mm in zip(elem_keys, mms):
  83. types_to_name_nodes.setdefault(mm, set()).add(key)
  84. # And now we have the inverse mapping: for each type, we have the node containing the name
  85. # Get the inheritance link type
  86. inheritance_type, = yield [("RD", [m3_model, "Inheritance"])]
  87. # Now we figure out which types are valid for the specified model
  88. desired_types = set()
  89. mm_element, = yield [("RD", [mm_dict, b_val])]
  90. work_list = []
  91. work_list.append(mm_element)
  92. mm_typing, = yield [("RD", [metamodel, "type_mapping"])]
  93. while work_list:
  94. mm_element = work_list.pop()
  95. if mm_element in desired_types:
  96. # Already been here, so stop
  97. continue
  98. # New element, so continue
  99. desired_types.add(mm_element)
  100. # Follow all inheritance links that COME IN this node, as all these are subtypes and should also match
  101. incoming, = yield [("RI", [mm_element])]
  102. for i in incoming:
  103. t, = yield [("RDN", [mm_typing, i])]
  104. if t == inheritance_type:
  105. e, = yield [("RE", [i])]
  106. # Add the source of the inheritance link to the work list
  107. work_list.append(e[0])
  108. # Now desired_types holds all the direct types that we are interested in!
  109. # Construct the result out of all models that are direct instances of our specified type
  110. final = set()
  111. for t in desired_types:
  112. final |= types_to_name_nodes.get(t, set())
  113. # Result is a Python set with nodes, so just make this a Mv set
  114. result, = yield [("CN", [])]
  115. v = yield [("RV", [i]) for i in final]
  116. _ = yield [("CE", [result, i]) for i in final]
  117. raise PrimitiveFinished(result)
  118. """
  119. """
  120. def add_AL(a, b, **remainder):
  121. worklist = [(b, "funcdef")]
  122. added = set()
  123. type_cache = {}
  124. model_dict, = yield [("RD", [a, "model"])]
  125. metamodel, = yield [("RD", [a, "metamodel"])]
  126. metamodel_dict, = yield [("RD", [metamodel, "model"])]
  127. type_map, = yield [("RD", [a, "type_mapping"])]
  128. outgoing, = yield [("RO", [model_dict])]
  129. edges = yield [("RE", [i]) for i in outgoing]
  130. added |= set([i[1] for i in edges])
  131. result, = yield [("CNV", ["__%s" % b])]
  132. # All the action language elements and their expected output links
  133. type_links = {
  134. "if": [("cond", ""), ("then", ""), ("else", ""), ("next", "")],
  135. "while": [("cond", ""), ("body", ""), ("next", "")],
  136. "assign": [("var", ""), ("value", ""), ("next", "")],
  137. "break": [("while", "while")],
  138. "continue": [("while", "while")],
  139. "return": [("value", "")],
  140. "resolve": [("var", "")],
  141. "access": [("var", "")],
  142. "constant": [("node", "")],
  143. "output": [("node", ""), ("next", "")],
  144. "global": [("var", "String"), ("next", "")],
  145. "param": [("name", "String"), ("value", ""), ("next_param", "param")],
  146. "funcdef": [("body", ""), ("next", "")],
  147. "call": [("func", ""), ("params", "param"), ("last_param", "param"), ("next", "")],
  148. }
  149. # Already add some often used types to the type cache, so we don't have to check for their presence
  150. to_str, string = yield [("CNV", ["to_str"]),
  151. ("CNV", ["String"])]
  152. type_cache = {"to_str": to_str,
  153. "String": string}
  154. while worklist:
  155. # Fetch the element and see if we need to add it
  156. worknode, expected_type = worklist.pop(0)
  157. if worknode in added:
  158. continue
  159. # Determine type of element
  160. if expected_type == "":
  161. value, = yield [("RV", [worknode])]
  162. if (isinstance(value, dict)) and ("value" in value):
  163. v = value["value"]
  164. if v in ["if", "while", "assign", "call", "break", "continue", "return", "resolve", "access", "constant", "global", "declare"]:
  165. expected_type = v
  166. else:
  167. expected_type = "Any"
  168. else:
  169. expected_type = "Any"
  170. # Fill the cache
  171. if expected_type not in type_cache:
  172. type_cache[expected_type], = yield [("CNV", [expected_type])]
  173. # Need to add it now
  174. nodename = "__%s" % worknode
  175. yield [("CD", [model_dict, nodename, worknode])]
  176. added.add(worknode)
  177. _, = yield [("CD", [type_map, nodename, type_cache[expected_type]])]
  178. # Now add all its outgoing links, depending on the type we actually saw
  179. links = type_links.get(expected_type, [])
  180. for link in links:
  181. link_name, destination_type = link
  182. # Check if the link actually exists
  183. destination, = yield [("RD", [worknode, link_name])]
  184. if destination is not None:
  185. # If so, we add it and continue
  186. edge, = yield [("RDE", [worknode, link_name])]
  187. edge_outlinks, = yield [("RO", [edge])]
  188. edge_outlink = edge_outlinks[0]
  189. edge_name, = yield [("RE", [edge_outlink])]
  190. edge_name = edge_name[1]
  191. # Now add: edge, edge_outlink, edge_name
  192. # Add 'edge'
  193. edgename = "__%s" % edge
  194. yield [("CD", [model_dict, edgename, edge])]
  195. added.add(edge)
  196. link_type = "%s_%s" % (expected_type, link_name)
  197. if link_type not in type_cache:
  198. type_cache[link_type], = yield [("CNV", [link_type])]
  199. _, = yield [("CD", [type_map, edge_name, type_cache[link_type]])]
  200. # Add 'edge_outlink'
  201. edgename = "__%s" % edge_outlink
  202. yield [("CD", [model_dict, edgename, edge_outlink])]
  203. added.add(edge_outlink)
  204. _, = yield [("CD", [type_map, edgename, type_cache["to_str"]])]
  205. # Add 'edge_name' (if not present)
  206. if edge_name not in added:
  207. edgename = "__%s" % edge_name
  208. yield [("CD", [model_dict, edgename, edge_name])]
  209. _, = yield [("CD", [type_map, edgename, type_cache["String"]])]
  210. added.add(edge_name)
  211. # Add the destination to the worklist
  212. worklist.append((destination, destination_type))
  213. raise PrimitiveFinished(result)
  214. """
  215. """
  216. def get_superclasses(a, b, **remainder):
  217. mm, = yield [("RD", [a, "metamodel"])]
  218. mm, = yield [("RD", [mm, "metamodel"])]
  219. m, = yield [("RD", [mm, "model"])]
  220. inheritance, = yield [("RD", [m, "Inheritance"])]
  221. model_dict, = yield [("RD", [a, "model"])]
  222. b_v, = yield [("RV", [b])]
  223. subclass, = yield [("RD", [model_dict, b_v])]
  224. type_mapping, = yield [("RD", [a, "type_mapping"])]
  225. names, = yield [("RDK", [model_dict])]
  226. elems = yield [("RDN", [model_dict, i]) for i in names]
  227. elem_to_name = dict(zip(elems, names))
  228. result, = yield [("CN", [])]
  229. worklist = [subclass]
  230. touched = set()
  231. while worklist:
  232. subclass = worklist.pop()
  233. res = elem_to_name[subclass]
  234. if subclass not in touched:
  235. touched.add(subclass)
  236. yield [("CE", [result, res])]
  237. outgoing, = yield [("RO", [subclass])]
  238. types = yield [("RDN", [type_mapping, i]) for i in outgoing]
  239. for i, t in enumerate(types):
  240. if t == inheritance:
  241. # Found an inheritance link!
  242. elem = outgoing[i]
  243. srcdst, = yield [("RE", [elem])]
  244. src, dst = srcdst
  245. # Find elem in elems
  246. worklist.append(dst)
  247. if dst is None:
  248. print("Read edge gives error for edge: " + str(elem))
  249. raise PrimitiveFinished(result)
  250. """
  251. """
  252. def selectPossibleIncoming(a, b, c, **remainder):
  253. model_dict, = yield [("RD", [a, "model"])]
  254. limit_set_links, = \
  255. yield [("RO", [c])]
  256. limit_set = yield [("RE", [i]) for i in limit_set_links]
  257. limit_set_names = [i[1] for i in limit_set]
  258. name_values = yield [("RV", [i]) for i in limit_set_names]
  259. limit_set = yield [("RD", [model_dict, i]) for i in name_values]
  260. superclasses, = yield [("CALL_ARGS", [get_superclasses, (a, b)])]
  261. vals, = yield [("RO", [superclasses])]
  262. superclasses = yield [("RE", [i]) for i in vals]
  263. superclasses = [i[1] for i in superclasses]
  264. superclass_names = yield [("RV", [i]) for i in superclasses]
  265. elems = yield [("RD", [model_dict, i]) for i in superclass_names]
  266. result, = yield [("CN", [])]
  267. for i, edge in enumerate(limit_set):
  268. srcdst, = yield [("RE", [edge])]
  269. src, dst = srcdst
  270. if dst in elems:
  271. yield [("CE", [result, limit_set_names[i]])]
  272. raise PrimitiveFinished(result)
  273. """
  274. """
  275. def selectPossibleOutgoing(a, b, c, **remainder):
  276. model_dict, = yield [("RD", [a, "model"])]
  277. limit_set_links, = \
  278. yield [("RO", [c])]
  279. limit_set = yield [("RE", [i]) for i in limit_set_links]
  280. limit_set_names = \
  281. [i[1] for i in limit_set]
  282. name_values = yield [("RV", [i]) for i in limit_set_names]
  283. limit_set = yield [("RD", [model_dict, i]) for i in name_values]
  284. superclasses, = yield [("CALL_ARGS", [get_superclasses, (a, b)])]
  285. vals, = yield [("RO", [superclasses])]
  286. superclasses = yield [("RE", [i]) for i in vals]
  287. superclasses = [i[1] for i in superclasses]
  288. superclass_names = yield [("RV", [i]) for i in superclasses]
  289. elems = yield [("RD", [model_dict, i]) for i in superclass_names]
  290. result, = yield [("CN", [])]
  291. for i, edge in enumerate(limit_set):
  292. srcdst, = yield [("RE", [edge])]
  293. src, dst = srcdst
  294. if src in elems:
  295. yield [("CE", [result, limit_set_names[i]])]
  296. raise PrimitiveFinished(result)
  297. """
  298. def check_symbols(a, b, c, **remainder):
  299. symbols = {}
  300. function_name, = yield [("RV", [b])]
  301. symbols[function_name] = False
  302. object_links, = yield [("RO", [c])]
  303. set_elements = yield [("RE", [i]) for i in object_links]
  304. set_elements = [i[1] for i in set_elements]
  305. set_values = yield [("RV", [i]) for i in set_elements]
  306. set_elements = yield [("RD", [a, i]) for i in set_values]
  307. symbols_set = yield [("RD", [i, "symbols"]) for i in set_elements]
  308. all_keys = yield [("RDK", [i]) for i in symbols_set]
  309. for i, s in zip(all_keys, symbols_set):
  310. # For each object we have found
  311. keys = yield [("RV", [j]) for j in i]
  312. values = yield [("RD", [s, j]) for j in keys]
  313. values = yield [("RV", [j]) for j in values]
  314. for key, value in zip(keys, values):
  315. k = key
  316. v = value
  317. if v and symbols.get(k, False):
  318. result, = yield [("CNV", ["ERROR: multiple definition of symbol " + str(key)])]
  319. raise PrimitiveFinished(result)
  320. elif v and not symbols.get(k, False):
  321. symbols[k] = True
  322. elif not v and k not in symbols:
  323. symbols[k] = False
  324. for i, j in symbols.items():
  325. if i == "input" or i == "output":
  326. continue
  327. if not j:
  328. result, = yield [("CNV", ["ERROR: undefined symbol " + str(i)])]
  329. raise PrimitiveFinished(result)
  330. result, = yield [("CNV", ["OK"])]
  331. raise PrimitiveFinished(result)
  332. def construct_const(**remainder):
  333. v, = yield [("CNV", [{"value": "constant"}])]
  334. # Get input: keep trying until we get something
  335. inp, = yield [("CALL_KWARGS", [jit_runtime.get_input, remainder])]
  336. yield [("CD", [v, "node", inp])]
  337. raise PrimitiveFinished(v)
  338. def instantiated_name(a, b, **remainder):
  339. name_value, = yield [("RV", [b])]
  340. if name_value == "":
  341. b, = yield [("CNV", ["__" + str(a)])]
  342. raise PrimitiveFinished(b)