compiled_legacy.py 19 KB

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