primitives.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. # Exception to indicate the result value of the primitive, as a return cannot be used
  2. class PrimitiveFinished(Exception):
  3. def __init__(self, value):
  4. self.result = value
  5. def integer_subtraction(a, b, **remainder):
  6. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  7. result, = yield [("CNV", [a_value - b_value])]
  8. raise PrimitiveFinished(result)
  9. def integer_addition(a, b, **remainder):
  10. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  11. result, = yield [("CNV", [a_value + b_value])]
  12. raise PrimitiveFinished(result)
  13. def integer_multiplication(a, b, **remainder):
  14. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  15. result, = yield [("CNV", [a_value * b_value])]
  16. raise PrimitiveFinished(result)
  17. def integer_division(a, b, **remainder):
  18. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  19. result, = yield [("CNV", [int(a_value) / b_value])]
  20. raise PrimitiveFinished(result)
  21. def integer_gt(a, b, **remainder):
  22. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  23. result, = yield [("CNV", [a_value > b_value])]
  24. raise PrimitiveFinished(result)
  25. def integer_lt(a, b, **remainder):
  26. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  27. result, = yield [("CNV", [a_value < b_value])]
  28. raise PrimitiveFinished(result)
  29. def integer_neg(a, **remainder):
  30. a_value, = yield [("RV", [a])]
  31. result, = yield [("CNV", [-a_value])]
  32. raise PrimitiveFinished(result)
  33. def bool_and(a, b, **remainder):
  34. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  35. result, = yield [("CNV", [a_value and b_value])]
  36. raise PrimitiveFinished(result)
  37. def bool_or(a, b, **remainder):
  38. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  39. result, = yield [("CNV", [a_value or b_value])]
  40. raise PrimitiveFinished(result)
  41. def bool_not(a, **remainder):
  42. a_value, = yield [("RV", [a])]
  43. result, = yield [("CNV", [not a_value])]
  44. raise PrimitiveFinished(result)
  45. def float_subtraction(a, b, **remainder):
  46. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  47. result, = yield [("CNV", [a_value - b_value])]
  48. raise PrimitiveFinished(result)
  49. def float_addition(a, b, **remainder):
  50. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  51. result, = yield [("CNV", [a_value + b_value])]
  52. raise PrimitiveFinished(result)
  53. def float_multiplication(a, b, **remainder):
  54. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  55. result, = yield [("CNV", [a_value * b_value])]
  56. raise PrimitiveFinished(result)
  57. def float_division(a, b, **remainder):
  58. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  59. result, = yield [("CNV", [float(a_value) / float(b_value)])]
  60. raise PrimitiveFinished(result)
  61. def float_gt(a, b, **remainder):
  62. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  63. result, = yield [("CNV", [a_value > b_value])]
  64. raise PrimitiveFinished(result)
  65. def float_lt(a, b, **remainder):
  66. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  67. result, = yield [("CNV", [a_value < b_value])]
  68. raise PrimitiveFinished(result)
  69. def float_neg(a, **remainder):
  70. a_value, = yield [("RV", [a])]
  71. result, = yield [("CNV", [-a_value])]
  72. raise PrimitiveFinished(result)
  73. def string_join(a, b, **remainder):
  74. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  75. result, = yield [("CNV", [str(a_value) + str(b_value)])]
  76. raise PrimitiveFinished(result)
  77. def string_split(a, b, **remainder):
  78. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  79. result = a_value.split(b_value)
  80. elems = yield [("CN", [])] + [("CNV", [v]) for v in result]
  81. new_val = elems[0]
  82. yield [("CD", [new_val, i, v]) for i, v in enumerate(elems[1:])]
  83. raise PrimitiveFinished(new_val)
  84. def string_get(a, b, **remainder):
  85. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  86. result, = yield [("CNV", [a_value[b_value]])]
  87. raise PrimitiveFinished(result)
  88. def string_len(a, **remainder):
  89. a_value, = yield [("RV", [a])]
  90. result, = yield [("CNV", [len(a_value)])]
  91. raise PrimitiveFinished(result)
  92. def value_eq(a, b, **remainder):
  93. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  94. result, = yield [("CNV", [a_value == b_value])]
  95. raise PrimitiveFinished(result)
  96. def value_neq(a, b, **remainder):
  97. a_value, b_value = yield [("RV", [a]), ("RV", [b])]
  98. result, = yield [("CNV", [a_value != b_value])]
  99. raise PrimitiveFinished(result)
  100. def element_eq(a, b, **remainder):
  101. result, = yield [("CNV", [a == b])]
  102. raise PrimitiveFinished(result)
  103. def element_neq(a, b, **remainder):
  104. result, = yield [("CNV", [a != b])]
  105. raise PrimitiveFinished(result)
  106. def cast_a2s(a, **remainder):
  107. a_value, = yield [("RV", [a])]
  108. result, = yield [("CNV", [str(a_value["value"])])]
  109. raise PrimitiveFinished(result)
  110. def cast_i2f(a, **remainder):
  111. a_value, = yield [("RV", [a])]
  112. result, = yield [("CNV", [float(a_value)])]
  113. raise PrimitiveFinished(result)
  114. def cast_i2s(a, **remainder):
  115. a_value, = yield [("RV", [a])]
  116. result, = yield [("CNV", [str(a_value)])]
  117. raise PrimitiveFinished(result)
  118. def cast_i2b(a, **remainder):
  119. a_value, = yield [("RV", [a])]
  120. result, = yield [("CNV", [bool(a_value)])]
  121. raise PrimitiveFinished(result)
  122. def cast_f2i(a, **remainder):
  123. a_value, = yield [("RV", [a])]
  124. result, = yield [("CNV", [int(a_value)])]
  125. raise PrimitiveFinished(result)
  126. def cast_f2s(a, **remainder):
  127. a_value, = yield [("RV", [a])]
  128. result, = yield [("CNV", [str(a_value)])]
  129. raise PrimitiveFinished(result)
  130. def cast_f2b(a, **remainder):
  131. a_value, = yield [("RV", [a])]
  132. result, = yield [("CNV", [bool(a_value)])]
  133. raise PrimitiveFinished(result)
  134. def cast_s2i(a, **remainder):
  135. a_value, = yield [("RV", [a])]
  136. result, = yield [("CNV", [int(a_value)])]
  137. raise PrimitiveFinished(result)
  138. def cast_s2f(a, **remainder):
  139. a_value, = yield [("RV", [a])]
  140. result, = yield [("CNV", [float(a_value)])]
  141. raise PrimitiveFinished(result)
  142. def cast_s2b(a, **remainder):
  143. a_value, = yield [("RV", [a])]
  144. result, = yield [("CNV", [bool(a_value)])]
  145. raise PrimitiveFinished(result)
  146. def cast_b2i(a, **remainder):
  147. a_value, = yield [("RV", [a])]
  148. result, = yield [("CNV", [int(a_value)])]
  149. raise PrimitiveFinished(result)
  150. def cast_b2f(a, **remainder):
  151. a_value, = yield [("RV", [a])]
  152. result, = yield [("CNV", [float(a_value)])]
  153. raise PrimitiveFinished(result)
  154. def cast_b2s(a, **remainder):
  155. a_value, = yield [("RV", [a])]
  156. result, = yield [("CNV", [str(a_value)])]
  157. raise PrimitiveFinished(result)
  158. def cast_e2s(a, **remainder):
  159. a_value, = yield [("RV", [a])]
  160. result, = yield [("CNV", ["{ID: %s, value: %s}" % (a, a_value)])]
  161. raise PrimitiveFinished(result)
  162. def cast_v2s(a, **remainder):
  163. a_value, = yield [("RV", [a])]
  164. if isinstance(a_value, (str, unicode)):
  165. # String should be encoded to distinguish between 3 and "3"
  166. a_value = '"%s"' % a_value
  167. elif isinstance(a_value, dict):
  168. # Action or type
  169. a_value = a_value["value"]
  170. result, = yield [("CNV", ["%s" % (a_value)])]
  171. raise PrimitiveFinished(result)
  172. def cast_id2s(a, **remainder):
  173. result, = yield [("CNV", ["%s" % (a)])]
  174. raise PrimitiveFinished(result)
  175. def list_append(a, b, **remainder):
  176. a_outgoing, = yield [("RO", [a])]
  177. _ = yield [("CD", [a, len(a_outgoing), b])]
  178. raise PrimitiveFinished(a)
  179. def list_insert(a, b, c, **remainder):
  180. a_outgoing, c_value = yield [("RO", [a]), ("RV", [c])]
  181. links = yield [("RD", [a, i]) for i in range(c_value, len(a_outgoing))] + \
  182. [("RDE", [a, i]) for i in range(c_value, len(a_outgoing))]
  183. values = links[:len(links)/2]
  184. edges = links[len(links)/2:]
  185. yield [("CD", [a, c_value, b])] + \
  186. [("CD", [a, c_value + 1 + index, value]) for index, value in enumerate(values)] + \
  187. [("DE", [i]) for i in edges]
  188. raise PrimitiveFinished(a)
  189. def list_delete(a, b, **remainder):
  190. a_outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
  191. links = yield [("RD", [a, i]) for i in range(b_value, len(a_outgoing))] + \
  192. [("RDE", [a, i]) for i in range(b_value, len(a_outgoing))]
  193. values = links[:len(links)/2]
  194. edges = links[len(links)/2:]
  195. yield [("CD", [a, b_value + index, value]) for index, value in enumerate(values[1:])] + \
  196. [("DE", [i]) for i in edges]
  197. raise PrimitiveFinished(a)
  198. def list_read(a, b, **remainder):
  199. b_value, = yield [("RV", [b])]
  200. result, = yield [("RD", [a, b_value])]
  201. if result is None:
  202. raise Exception("List read out of bounds: %s" % b_value)
  203. raise PrimitiveFinished(result)
  204. def list_len(a, **remainder):
  205. outgoings, = yield [("RO", [a])]
  206. result, = yield [("CNV", [len(outgoings)])]
  207. raise PrimitiveFinished(result)
  208. def dict_add(a, b, c, **remainder):
  209. new_edge, = yield [("CE", [a, c])]
  210. yield [("CE", [new_edge, b])]
  211. raise PrimitiveFinished(a)
  212. def dict_delete(a, b, **remainder):
  213. b_value, = yield [("RV", [b])]
  214. edge, = yield [("RDE", [a, b_value])]
  215. if edge is None:
  216. print("Failed dict_delete for value %s!" % b_value)
  217. keys, = yield [("RDK", [a])]
  218. keys = yield [("RV", [i]) for i in keys]
  219. print("Keys: " + str(keys))
  220. yield [("DE", [edge])]
  221. raise PrimitiveFinished(a)
  222. def dict_delete_node(a, b, **remainder):
  223. edge, = yield [("RDNE", [a, b])]
  224. if edge is None:
  225. print("Failed dict_delete_node!")
  226. yield [("DE", [edge])]
  227. raise PrimitiveFinished(a)
  228. def dict_read(a, b, **remainder):
  229. b_value, = yield [("RV", [b])]
  230. result, = yield [("RD", [a, b_value])]
  231. raise PrimitiveFinished(result)
  232. def dict_read_edge(a, b, **remainder):
  233. b_value, = yield [("RV", [b])]
  234. result, = yield [("RDE", [a, b_value])]
  235. raise PrimitiveFinished(result)
  236. def dict_read_node(a, b, **remainder):
  237. result, = yield [("RDN", [a, b])]
  238. raise PrimitiveFinished(result)
  239. def dict_in(a, b, **remainder):
  240. b_value, = yield [("RV", [b])]
  241. value, = yield [("RD", [a, b_value])]
  242. is_in = value is not None
  243. result, = yield [("CNV", [is_in])]
  244. raise PrimitiveFinished(result)
  245. def dict_in_node(a, b, **remainder):
  246. value, = yield [("RDN", [a, b])]
  247. result, = yield [("CNV", [value is not None])]
  248. raise PrimitiveFinished(result)
  249. def dict_len(a, **remainder):
  250. outgoings, = yield [("RO", [a])]
  251. result, = yield [("CNV", [len(outgoings)])]
  252. raise PrimitiveFinished(result)
  253. def dict_keys(a, **remainder):
  254. keys, result = yield [("RDK", [a]), ("CN", [])]
  255. yield [("CE", [result, v]) for v in keys]
  256. raise PrimitiveFinished(result)
  257. def dict_reverse(a, b, **remainder):
  258. edges, = yield [("RO", [a])]
  259. expanded_edges, = yield [("RE", [i]) for i in edges]
  260. for i, edge in enumerate(expanded_edges):
  261. if b == edge[1]:
  262. # Found our edge: edges[i]
  263. outgoing, = yield [("RO", [edges[i]])]
  264. result, = yield [("RE", [outgoing[0]])]
  265. raise PrimitiveFinished(result[1])
  266. result, = yield [("CNV", ["(unknown: %s)" % b])]
  267. raise PrimitiveFinished(result)
  268. def is_physical_int(a, **remainder):
  269. t, = yield [("RV", [a])]
  270. result, = yield [("CNV", [isinstance(t, int) or isinstance(t, long)])]
  271. raise PrimitiveFinished(result)
  272. def is_physical_string(a, **remainder):
  273. t, = yield [("RV", [a])]
  274. result, = yield [("CNV", [isinstance(t, str) or isinstance(t, unicode)])]
  275. raise PrimitiveFinished(result)
  276. def is_physical_float(a, **remainder):
  277. t, = yield [("RV", [a])]
  278. result, = yield [("CNV", [isinstance(t, float)])]
  279. raise PrimitiveFinished(result)
  280. def is_physical_boolean(a, **remainder):
  281. t, = yield [("RV", [a])]
  282. result, = yield [("CNV", [isinstance(t, bool)])]
  283. raise PrimitiveFinished(result)
  284. def is_physical_action(a, **remainder):
  285. t, = yield [("RV", [a])]
  286. result, = yield [("CNV", [isinstance(t, dict) and t["value"] in ["if", "while", "assign", "call", "break", "continue", "return", "resolve", "access", "constant", "global", "declare"]])]
  287. raise PrimitiveFinished(result)
  288. def create_node(**remainder):
  289. result, = yield [("CN", [])]
  290. raise PrimitiveFinished(result)
  291. def create_edge(a, b, **remainder):
  292. result, = yield [("CE", [a, b])]
  293. raise PrimitiveFinished(result)
  294. def create_value(a, **remainder):
  295. a_value, = yield [("RV", [a])]
  296. result, = yield [("CNV", [a_value])]
  297. raise PrimitiveFinished(result)
  298. def read_nr_out(a, **remainder):
  299. outgoing, = yield [("RO", [a])]
  300. result, = yield [("CNV", [len(outgoing)])]
  301. raise PrimitiveFinished(result)
  302. def read_out(a, b, **remainder):
  303. outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
  304. raise PrimitiveFinished(sorted(outgoing)[b_value])
  305. def read_nr_in(a, **remainder):
  306. incoming, = yield [("RI", [a])]
  307. result, = yield [("CNV", [len(incoming)])]
  308. raise PrimitiveFinished(result)
  309. def read_in(a, b, **remainder):
  310. incoming, b_value = yield [("RI", [a]), ("RV", [b])]
  311. raise PrimitiveFinished(sorted(incoming)[b_value])
  312. def read_edge_src(a, **remainder):
  313. result, = yield [("RE", [a])]
  314. raise PrimitiveFinished(result[0])
  315. def read_edge_dst(a, **remainder):
  316. result, = yield [("RE", [a])]
  317. raise PrimitiveFinished(result[1])
  318. def delete_element(a, **remainder):
  319. edge, = yield [("RE", [a])]
  320. if edge[0] is None:
  321. # Not an edge:
  322. yield [("DN", [a])]
  323. result, = yield [("CNV", [False])]
  324. raise PrimitiveFinished(result)
  325. else:
  326. yield [("DE", [a])]
  327. result, = yield [("CNV", [True])]
  328. raise PrimitiveFinished(result)
  329. def read_root(root, **remainder):
  330. raise PrimitiveFinished(root)
  331. def set_add(a, b, **remainder):
  332. yield [("CE", [a, b])]
  333. raise PrimitiveFinished(a)
  334. def set_pop(a, **remainder):
  335. outgoing, = yield [("RO", [a])]
  336. v, _ = yield [("RE", [outgoing[0]]), ("DE", [outgoing[0]])]
  337. raise PrimitiveFinished(v[1])
  338. def set_remove(a, b, **remainder):
  339. outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
  340. elements = yield [("RE", [i]) for i in outgoing]
  341. values = yield [("RV", [i[1]]) for i in elements]
  342. yield [("DE", [identifier]) for identifier, edge in zip(outgoing, values) if edge == b_value]
  343. raise PrimitiveFinished(a)
  344. def set_remove_node(a, b, **remainder):
  345. outgoing, = yield [("RO", [a])]
  346. elements = yield [("RE", [i]) for i in outgoing]
  347. elements = [elements] if not isinstance(elements[0], list) else elements
  348. yield [("DE", [identifier]) for identifier, edge in zip(outgoing, elements) if edge[1] == b]
  349. raise PrimitiveFinished(a)
  350. def set_in(a, b, **remainder):
  351. outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
  352. if outgoing:
  353. elements = yield [("RE", [i]) for i in outgoing]
  354. values = yield [("RV", [i[1]]) for i in elements]
  355. if b_value in [v for v in values]:
  356. result, = yield [("CNV", [True])]
  357. else:
  358. result, = yield [("CNV", [False])]
  359. else:
  360. result, = yield [("CNV", [False])]
  361. raise PrimitiveFinished(result)
  362. def set_in_node(a, b, **remainder):
  363. outgoing, = yield [("RO", [a])]
  364. if outgoing:
  365. elements = yield [("RE", [i]) for i in outgoing]
  366. if b in [v[1] for v in elements]:
  367. result, = yield [("CNV", [True])]
  368. else:
  369. result, = yield [("CNV", [False])]
  370. else:
  371. result, = yield [("CNV", [False])]
  372. raise PrimitiveFinished(result)
  373. def is_edge(a, **remainder):
  374. edge, = yield [("RE", [a])]
  375. result, = yield [("CNV", [edge[0] is not None])]
  376. raise PrimitiveFinished(result)
  377. #TODO deprecate
  378. def deserialize(a, root, **remainder):
  379. print("DESERIALIZE")
  380. value, = yield [("RV", [a])]
  381. id_mappings = {}
  382. complex_primitives = frozenset(["if", "while", "assign", "call", "break", "continue", "return","resolve","access", "constant", "input", "output", "declare", "global"])
  383. for l in value.split("\n"):
  384. try:
  385. graph_type, constructor = l.split(None, 1)
  386. except:
  387. continue
  388. if graph_type == "N":
  389. # Node
  390. id_mappings[constructor], = yield [("CN", [])]
  391. elif graph_type == "V":
  392. # Node with Value
  393. name, temp = constructor.split("(", 1)
  394. string_value = temp[:-1]
  395. if string_value in complex_primitives:
  396. value = {"value": string_value}
  397. else:
  398. #TODO this is very dangerous!
  399. value = eval(string_value)
  400. id_mappings[name], = yield [("CNV", [value])]
  401. elif graph_type == "E":
  402. # Edge
  403. name, temp = constructor.split("(", 1)
  404. source, target = temp[:-1].split(",", 1)
  405. if target[0] == "?" and target not in id_mappings:
  406. hierarchy = target[1:].split("/")
  407. current, = yield [("RD", [root, "__hierarchy"])]
  408. for i in hierarchy:
  409. current, = yield [("RD", [current, i])]
  410. id_mappings[target] = current
  411. try:
  412. source = int(source)
  413. except:
  414. source = id_mappings[source]
  415. try:
  416. target = int(target)
  417. except:
  418. target = id_mappings[target]
  419. # Both nodes will normally be already present in the matching dictionary, so can just pass them along
  420. id_mappings[name], = yield [("CE", [source, target])]
  421. elif graph_type == "D":
  422. source, value, target = constructor.split(",",3)
  423. if value in complex_primitives:
  424. value = {"value": value}
  425. else:
  426. #TODO this is very dangerous!
  427. value = eval(value)
  428. if target[0] == "?" and target not in id_mappings:
  429. hierarchy = target[1:].split("/")
  430. current, = yield [("RD", [root, "__hierarchy"])]
  431. for i in hierarchy:
  432. current, = yield [("RD", [current, i])]
  433. id_mappings[target] = current
  434. try:
  435. source = int(source)
  436. except:
  437. source = id_mappings[source]
  438. try:
  439. target = int(target)
  440. except:
  441. target = id_mappings[target]
  442. yield [("CD", [source, value, target])]
  443. else:
  444. print("Unknown graph type: " + str(graph_type))
  445. raise PrimitiveFinished(id_mappings["auto_initial_IP"])
  446. def log(a, **remainder):
  447. a_value, = yield [("RV", [a])]
  448. print("== LOG == " + str(a_value))
  449. raise PrimitiveFinished(a)
  450. def read_userroot(user_root, **remainder):
  451. raise PrimitiveFinished(user_root)