primitives.py 19 KB

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