legacy.py 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. """A legacy version of the Modelverse kernel. This kernel can be used as a baseline for the
  2. performance of newer kernels."""
  3. import modelverse_kernel.primitives as primitive_functions
  4. import modelverse_kernel.compiled_legacy as compiled_functions
  5. from collections import defaultdict
  6. import sys
  7. import time
  8. if sys.version > '3': # pragma: no cover
  9. string_types = (str,)
  10. else:
  11. string_types = (str, unicode)
  12. class ModelverseKernel(object):
  13. def __init__(self, root):
  14. self.root = root
  15. self.primitives = {}
  16. self.compiled = {}
  17. self.returnvalue = None
  18. self.success = True
  19. self.generators = {}
  20. self.allow_compiled = True
  21. #self.allow_compiled = False
  22. self.debug_info = defaultdict(list)
  23. def execute_yields(self, taskname, operation, params, reply):
  24. try:
  25. self.success = True
  26. self.taskname = taskname
  27. if taskname not in self.generators:
  28. self.generators[taskname] = {}
  29. if operation not in self.generators[taskname]:
  30. # Create the generator for the function to execute
  31. self.generators[taskname][operation] = getattr(self, operation)(taskname, *params)
  32. if reply is not None:
  33. return self.generators[taskname][operation].send(reply)
  34. else:
  35. return self.generators[taskname][operation].next()
  36. except StopIteration:
  37. # Done, so remove the generator
  38. del self.generators[taskname][operation]
  39. return None
  40. except:
  41. print("Unknown error @ %s" % self.debug_info[taskname])
  42. raise
  43. def execute_rule(self, taskname):
  44. task_root, = yield [("RD", [self.root, taskname])]
  45. if task_root is None:
  46. self.success = False
  47. self.returnvalue = None
  48. yield None
  49. else:
  50. task_frame, = yield [("RD", [task_root, "frame"])]
  51. self.inst, phase = yield [("RD", [task_frame, "IP"]),
  52. ("RD", [task_frame, "phase"]),
  53. ]
  54. self.new_debug, self.phase_v, inst_v = \
  55. yield [("RD", [self.inst, "__debug"]),
  56. ("RV", [phase]),
  57. ("RV", [self.inst]),
  58. ]
  59. if self.new_debug is not None:
  60. if self.debug_info[taskname]:
  61. self.debug_info[taskname][-1], = yield [("RV", [self.new_debug])]
  62. if self.phase_v == "finish":
  63. gen = self.helper_init(task_root)
  64. elif self.inst is None:
  65. raise Exception("Instruction pointer could not be found!")
  66. elif isinstance(self.phase_v, string_types):
  67. if self.phase_v == "init" and self.inst in self.compiled:
  68. #print("%-30s(%s)" % ("COMPILED " + str(self.compiled[self.inst]), self.phase_v))
  69. gen = self.execute_primitive(task_root, self.inst, taskname)
  70. elif inst_v is None:
  71. raise Exception("%s: error understanding command (%s, %s)" % (self.debug_info[taskname], inst_v, self.phase_v))
  72. else:
  73. #print("%-30s(%s) -- %s" % (inst_v["value"], self.phase_v, taskname))
  74. gen = getattr(self, "%s_%s" % (inst_v["value"], self.phase_v))(task_root)
  75. elif inst_v is None:
  76. raise Exception("%s: error understanding command (%s, %s)" % (self.debug_info[taskname], inst_v, self.phase_v))
  77. elif inst_v["value"] == "call":
  78. #print("%-30s(%s)" % ("call", "param"))
  79. gen = self.call_param(task_root)
  80. else:
  81. raise Exception("%s: error understanding command (%s, %s)" % (self.debug_info[taskname], inst_v, self.phase_v))
  82. try:
  83. inp = None
  84. while 1:
  85. inp = yield gen.send(inp)
  86. except StopIteration:
  87. pass
  88. ##########################
  89. ### Process primitives ###
  90. ##########################
  91. def load_primitives(self, taskname):
  92. hierarchy, = yield [("RD", [self.root, "__hierarchy"])]
  93. primitives, = yield [("RD", [hierarchy, "primitives"])]
  94. keys, = yield [("RDK", [primitives])]
  95. function_names = yield [("RV", [f]) for f in keys]
  96. signatures = yield [("RDN", [primitives, f]) for f in keys]
  97. bodies = yield [("RD", [f, "body"]) for f in signatures]
  98. for i in range(len(keys)):
  99. self.primitives[bodies[i]] = getattr(primitive_functions, function_names[i])
  100. self.compiled.update(self.primitives)
  101. def execute_primitive(self, task_root, inst, taskname):
  102. # execute_primitive
  103. task_frame, = yield [("RD", [task_root, "frame"])]
  104. symbols, = yield [("RD", [task_frame, "symbols"])]
  105. all_links, = yield [("RO", [symbols])]
  106. containers = yield [("RE", [v]) for v in all_links]
  107. outgoings = yield [("RO", [v]) for v in all_links]
  108. dict_values = yield [("RD", [v[1], "value"]) for v in containers]
  109. formals_1 = yield [("RE", [v[0]]) for v in outgoings]
  110. dict_keys_ref = yield [("RD", [v[1], "name"]) for v in formals_1]
  111. dict_keys = yield [("RV", [v]) for v in dict_keys_ref]
  112. parameters = dict(zip(dict_keys, dict_values))
  113. parameters["root"] = self.root
  114. parameters["task_root"] = task_root
  115. parameters["taskname"] = taskname
  116. parameters["mvk"] = self
  117. # prim is a generator itself!
  118. try:
  119. # Forward the message we get to this generator
  120. # Sometimes it might not even be a generator, in which case this should already be in the except block (i.e., for the Read Root operation)
  121. prim = self.compiled[inst](**parameters)
  122. inp = None
  123. while 1:
  124. inp = yield prim.send(inp)
  125. except StopIteration:
  126. # Execution has ended without return value, so we have no idea what to do
  127. raise Exception("%s: primitive finished without returning a value!" % (self.debug_info[taskname]))
  128. except primitive_functions.PrimitiveFinished as e:
  129. # Execution has ended with a returnvalue, so read it out from the exception being thrown
  130. result = e.result
  131. #if result is None:
  132. # raise Exception("Primitive raised exception: value of None for operation %s with parameters %s" % (self.compiled[inst], str(parameters)))
  133. # Clean up the current stack, as if a return happened
  134. old_frame, = yield [("RD", [task_frame, "prev"])]
  135. lnk, = yield [("RDE", [old_frame, "returnvalue"])]
  136. _, _, _, _ = yield [("CD", [old_frame, "returnvalue", result]),
  137. ("CD", [task_root, "frame", old_frame]),
  138. ("DE", [lnk]),
  139. ("DN", [task_frame]),
  140. ]
  141. if self.debug_info[self.taskname]:
  142. self.debug_info[self.taskname].pop()
  143. ########################################
  144. ### Execute input and output methods ###
  145. ########################################
  146. def get_output(self, taskname):
  147. task_root, = yield [("RD", [self.root, taskname])]
  148. first_output, = yield [("RD", [task_root, "output"])]
  149. next_output, rv = yield [("RD", [first_output, "next"]),
  150. ("RD", [first_output, "value"]),
  151. ]
  152. if next_output is None:
  153. self.success = False
  154. self.returnvalue = None
  155. else:
  156. rv_value, = yield [("RV", [rv])]
  157. _, _ = yield [("CD", [task_root, "output", next_output]),
  158. ("DN", [first_output]),
  159. ]
  160. self.returnvalue = rv_value
  161. def set_input(self, taskname, value):
  162. task_root, = yield [("RD", [self.root, taskname])]
  163. old_input, link = yield [("RD", [task_root, "last_input"]),
  164. ("RDE", [task_root, "last_input"]),
  165. ]
  166. new_input, = yield [("CN", [])]
  167. _, _ = yield [("CD", [task_root, "last_input", new_input]),
  168. ("CD", [old_input, "next", new_input]),
  169. ]
  170. new_value, = yield [("CNV", [value])]
  171. _, _ = yield [("CD", [old_input, "value", new_value]),
  172. ("DE", [link])
  173. ]
  174. self.returnvalue = {"id": 100, "value": "success"}
  175. #############################################
  176. ### Transformation rules for instructions ###
  177. #############################################
  178. def continue_init(self, task_root):
  179. task_frame, = yield [("RD", [task_root, "frame"])]
  180. inst, = yield [("RD", [task_frame, "IP"])]
  181. while_inst, = yield [("RD", [inst, "while"])]
  182. old_evalstack_link, old_phase_link, evalstack_roots = \
  183. yield [("RDE", [task_frame, "evalstack"]),
  184. ("RDE", [task_frame, "phase"]),
  185. ("RRD", [while_inst, "inst"]),
  186. ]
  187. if len(evalstack_roots) == 1:
  188. evalstack_root = evalstack_roots[0]
  189. else:
  190. raise Exception("Could not process continue statement!")
  191. prev_evalstack_roots, old_evalstack_phase_link = \
  192. yield [("RRD", [evalstack_root, "prev"]),
  193. ("RDE", [evalstack_root, "phase"]),
  194. ]
  195. if len(prev_evalstack_roots) == 1:
  196. prev_evalstack_root = prev_evalstack_roots[0]
  197. else:
  198. raise Exception("Could not process continue statement!")
  199. new_evalstack_root, new_phase_while, new_phase_inst, prev_evalstack_root_link = \
  200. yield [("CN", []),
  201. ("CNV", ["init"]),
  202. ("CNV", ["finish"]),
  203. ("RDE", [prev_evalstack_root, "prev"]),
  204. ]
  205. _, _, _, _, _, _, _, _ = \
  206. yield [("CD", [task_frame, "evalstack", new_evalstack_root]),
  207. ("CD", [new_evalstack_root, "prev", evalstack_root]),
  208. ("CD", [task_frame, "phase", new_phase_inst]),
  209. ("CD", [evalstack_root, "phase", new_phase_while]),
  210. ("DE", [old_evalstack_link]),
  211. ("DE", [prev_evalstack_root_link]),
  212. ("DE", [old_phase_link]),
  213. ("DE", [old_evalstack_phase_link]),
  214. ]
  215. def break_init(self, task_root):
  216. task_frame, = yield [("RD", [task_root, "frame"])]
  217. inst, = yield [("RD", [task_frame, "IP"])]
  218. while_inst, = yield [("RD", [inst, "while"])]
  219. old_evalstack_link, old_phase_link, evalstack_roots = \
  220. yield [("RDE", [task_frame, "evalstack"]),
  221. ("RDE", [task_frame, "phase"]),
  222. ("RRD", [while_inst, "inst"]),
  223. ]
  224. if len(evalstack_roots) == 1:
  225. evalstack_root = evalstack_roots[0]
  226. else:
  227. raise Exception("Could not process break statement!")
  228. prev_evalstack_roots, old_evalstack_phase_link = \
  229. yield [("RRD", [evalstack_root, "prev"]),
  230. ("RDE", [evalstack_root, "phase"]),
  231. ]
  232. if len(prev_evalstack_roots) == 1:
  233. prev_evalstack_root = prev_evalstack_roots[0]
  234. else:
  235. raise Exception("Could not process break statement!")
  236. new_evalstack_root, new_phase_while, new_phase_inst, prev_evalstack_root_link = \
  237. yield [("CN", []),
  238. ("CNV", ["finish"]),
  239. ("CNV", ["finish"]),
  240. ("RDE", [prev_evalstack_root, "prev"]),
  241. ]
  242. _, _, _, _, _, _, _, _ = \
  243. yield [("CD", [task_frame, "evalstack", new_evalstack_root]),
  244. ("CD", [new_evalstack_root, "prev", evalstack_root]),
  245. ("CD", [task_frame, "phase", new_phase_inst]),
  246. ("CD", [evalstack_root, "phase", new_phase_while]),
  247. ("DE", [old_evalstack_link]),
  248. ("DE", [prev_evalstack_root_link]),
  249. ("DE", [old_phase_link]),
  250. ("DE", [old_evalstack_phase_link]),
  251. ]
  252. def if_init(self, task_root):
  253. task_frame, = yield [("RD", [task_root, "frame"])]
  254. evalstack, evalstack_link = \
  255. yield [("RD", [task_frame, "evalstack"]),
  256. ("RDE", [task_frame, "evalstack"]),
  257. ]
  258. inst, ip_link = yield [("RD", [task_frame, "IP"]),
  259. ("RDE", [task_frame, "IP"]),
  260. ]
  261. cond, = yield [("RD", [inst, "cond"])]
  262. new_evalstack, new_phase = \
  263. yield [("CN", []),
  264. ("CNV", ["cond"]),
  265. ]
  266. _, _, _, _, _, _, _ = \
  267. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  268. ("CD", [new_evalstack, "prev", evalstack]),
  269. ("CD", [task_frame, "IP", cond]),
  270. ("CD", [evalstack, "inst", inst]),
  271. ("CD", [evalstack, "phase", new_phase]),
  272. ("DE", [evalstack_link]),
  273. ("DE", [ip_link]),
  274. ]
  275. def if_cond(self, task_root):
  276. task_frame, = yield [("RD", [task_root, "frame"])]
  277. returnvalue, inst = yield [("RD", [task_frame, "returnvalue"]),
  278. ("RD", [task_frame, "IP"]),
  279. ]
  280. returnvalue_v, = yield [("RV", [returnvalue])]
  281. _else, = yield [("RD", [inst, "else"])]
  282. if returnvalue_v:
  283. phase_link, evalstack, evalstack_link, ip_link, _then, new_evalstack, evalstack_phase, new_phase = \
  284. yield [("RDE", [task_frame, "phase"]),
  285. ("RD", [task_frame, "evalstack"]),
  286. ("RDE", [task_frame, "evalstack"]),
  287. ("RDE", [task_frame, "IP"]),
  288. ("RD", [inst, "then"]),
  289. ("CN", []),
  290. ("CNV", ["finish"]),
  291. ("CNV", ["init"]),
  292. ]
  293. _, _, _, _, _, _, _, _, _ = \
  294. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  295. ("CD", [task_frame, "IP", _then]),
  296. ("CD", [new_evalstack, "prev", evalstack]),
  297. ("CD", [evalstack, "inst", inst]),
  298. ("CD", [evalstack, "phase", evalstack_phase]),
  299. ("CD", [task_frame, "phase", new_phase]),
  300. ("DE", [evalstack_link]),
  301. ("DE", [ip_link]),
  302. ("DE", [phase_link]),
  303. ]
  304. elif _else is None:
  305. phase_link, new_phase = \
  306. yield [("RDE", [task_frame, "phase"]),
  307. ("CNV", ["finish"]),
  308. ]
  309. _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  310. ("DE", [phase_link]),
  311. ]
  312. else:
  313. phase_link, evalstack, evalstack_link, ip_link = \
  314. yield [("RDE", [task_frame, "phase"]),
  315. ("RD", [task_frame, "evalstack"]),
  316. ("RDE", [task_frame, "evalstack"]),
  317. ("RDE", [task_frame, "IP"]),
  318. ]
  319. new_evalstack, new_phase, evalstack_phase = \
  320. yield [("CN", []),
  321. ("CNV", ["init"]),
  322. ("CNV", ["finish"]),
  323. ]
  324. _, _, _, _, _, _, _, _, _ = \
  325. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  326. ("CD", [task_frame, "IP", _else]),
  327. ("CD", [new_evalstack, "prev", evalstack]),
  328. ("CD", [evalstack, "inst", inst]),
  329. ("CD", [evalstack, "phase", evalstack_phase]),
  330. ("CD", [task_frame, "phase", new_phase]),
  331. ("DE", [evalstack_link]),
  332. ("DE", [ip_link]),
  333. ("DE", [phase_link]),
  334. ]
  335. def while_init(self, task_root):
  336. task_frame, = yield [("RD", [task_root, "frame"])]
  337. evalstack, evalstack_link, ip_link, inst = \
  338. yield [("RD", [task_frame, "evalstack"]),
  339. ("RDE", [task_frame, "evalstack"]),
  340. ("RDE", [task_frame, "IP"]),
  341. ("RD", [task_frame, "IP"]),
  342. ]
  343. cond, new_evalstack, new_phase = \
  344. yield [("RD", [inst, "cond"]),
  345. ("CN", []),
  346. ("CNV", ["cond"]),
  347. ]
  348. _, _, _, _, _, _, _ = \
  349. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  350. ("CD", [new_evalstack, "prev", evalstack]),
  351. ("CD", [task_frame, "IP", cond]),
  352. ("CD", [evalstack, "phase", new_phase]),
  353. ("CD", [evalstack, "inst", inst]),
  354. ("DE", [evalstack_link]),
  355. ("DE", [ip_link]),
  356. ]
  357. def while_cond(self, task_root):
  358. task_frame, = yield [("RD", [task_root, "frame"])]
  359. returnvalue, = yield [("RD", [task_frame, "returnvalue"])]
  360. returnvalue_v, = yield [("RV", [returnvalue])]
  361. if returnvalue_v:
  362. phase_link, evalstack, evalstack_link, ip_link, inst = \
  363. yield [("RDE", [task_frame, "phase"]),
  364. ("RD", [task_frame, "evalstack"]),
  365. ("RDE", [task_frame, "evalstack"]),
  366. ("RDE", [task_frame, "IP"]),
  367. ("RD", [task_frame, "IP"]),
  368. ]
  369. body, = yield [("RD", [inst, "body"])]
  370. new_evalstack, new_phase, evalstack_phase = \
  371. yield [("CN", []),
  372. ("CNV", ["init"]),
  373. ("CNV", ["init"]),
  374. ]
  375. _, _, _, _, _, _, _, _, _ = \
  376. yield [("CD", [task_frame, "IP", body]),
  377. ("CD", [task_frame, "phase", new_phase]),
  378. ("CD", [task_frame, "evalstack", new_evalstack]),
  379. ("CD", [new_evalstack, "prev", evalstack]),
  380. ("CD", [evalstack, "inst", inst]),
  381. ("CD", [evalstack, "phase", evalstack_phase]),
  382. ("DE", [evalstack_link]),
  383. ("DE", [ip_link]),
  384. ("DE", [phase_link]),
  385. ]
  386. else:
  387. phase_link, new_phase = \
  388. yield [("RDE", [task_frame, "phase"]),
  389. ("CNV", ["finish"]),
  390. ]
  391. _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  392. ("DE", [phase_link])
  393. ]
  394. def access_init(self, task_root):
  395. task_frame, = yield [("RD", [task_root, "frame"])]
  396. evalstack, evalstack_link, inst, ip_link = \
  397. yield [("RD", [task_frame, "evalstack"]),
  398. ("RDE", [task_frame, "evalstack"]),
  399. ("RD", [task_frame, "IP"]),
  400. ("RDE", [task_frame, "IP"]),
  401. ]
  402. var, new_evalstack, new_phase = \
  403. yield [("RD", [inst, "var"]),
  404. ("CN", []),
  405. ("CNV", ["eval"]),
  406. ]
  407. _, _, _, _, _, _, _ = \
  408. yield [("CD", [task_frame, "IP", var]),
  409. ("CD", [task_frame, "evalstack", new_evalstack]),
  410. ("CD", [new_evalstack, "prev", evalstack]),
  411. ("CD", [evalstack, "inst", inst]),
  412. ("CD", [evalstack, "phase", new_phase]),
  413. ("DE", [evalstack_link]),
  414. ("DE", [ip_link]),
  415. ]
  416. def access_eval(self, task_root):
  417. task_frame, = yield [("RD", [task_root, "frame"])]
  418. phase_link, returnvalue_link, returnvalue = \
  419. yield [("RDE", [task_frame, "phase"]),
  420. ("RDE", [task_frame, "returnvalue"]),
  421. ("RD", [task_frame, "returnvalue"]),
  422. ]
  423. value, new_phase = yield [("RD", [returnvalue, "value"]),
  424. ("CNV", ["finish"]),
  425. ]
  426. _, _, _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  427. ("CD", [task_frame, "returnvalue", value]),
  428. ("DE", [phase_link]),
  429. ("DE", [returnvalue_link]),
  430. ]
  431. def resolve_init(self, task_root):
  432. task_frame, = yield [("RD", [task_root, "frame"])]
  433. symbols, evalstack, evalstack_link, ip_link, inst = \
  434. yield [("RD", [task_frame, "symbols"]),
  435. ("RD", [task_frame, "evalstack"]),
  436. ("RDE", [task_frame, "evalstack"]),
  437. ("RDE", [task_frame, "IP"]),
  438. ("RD", [task_frame, "IP"]),
  439. ]
  440. var, = yield [("RD", [inst, "var"])]
  441. variable, = yield [("RDN", [symbols, var])]
  442. if variable is None:
  443. phase_link, returnvalue_link, _globals, var_name = \
  444. yield [("RDE", [task_frame, "phase"]),
  445. ("RDE", [task_frame, "returnvalue"]),
  446. ("RD", [task_root, "globals"]),
  447. ("RV", [var]),
  448. ]
  449. variable, new_phase = \
  450. yield [("RD", [_globals, var_name]),
  451. ("CNV", ["finish"]),
  452. ]
  453. if variable is None:
  454. raise Exception("Not found as global: %s" % var_name)
  455. # Resolved a global, so this is a string
  456. # Potentially, this might even be a function that we have precompiled already!
  457. # So check whether this is the case or not
  458. if self.allow_compiled:
  459. compiled_function = getattr(compiled_functions, var_name, None)
  460. if compiled_function is not None:
  461. # We have a compiled function ready!
  462. # Now we have to bind the ID to the compiled functions
  463. # For this, we read out the body of the resolved data
  464. compiler_val, = yield [("RD", [variable, "value"])]
  465. compiler_body, = yield [("RD", [compiler_val, "body"])]
  466. self.compiled[compiler_body] = compiled_function
  467. else:
  468. phase_link, returnvalue_link, new_phase = \
  469. yield [("RDE", [task_frame, "phase"]),
  470. ("RDE", [task_frame, "returnvalue"]),
  471. ("CNV", ["finish"]),
  472. ]
  473. _, _, _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  474. ("CD", [task_frame, "returnvalue", variable]),
  475. ("DE", [phase_link]),
  476. ("DE", [returnvalue_link]),
  477. ]
  478. def assign_init(self, task_root):
  479. task_frame, = yield [("RD", [task_root, "frame"])]
  480. evalstack, evalstack_link, ip_link, inst = \
  481. yield [("RD", [task_frame, "evalstack"]),
  482. ("RDE", [task_frame, "evalstack"]),
  483. ("RDE", [task_frame, "IP"]),
  484. ("RD", [task_frame, "IP"]),
  485. ]
  486. var, new_evalstack, new_phase = \
  487. yield [("RD", [inst, "var"]),
  488. ("CN", []),
  489. ("CNV", ["value"]),
  490. ]
  491. _, _, _, _, _, _, _ = \
  492. yield [("CD", [task_frame, "IP", var]),
  493. ("CD", [task_frame, "evalstack", new_evalstack]),
  494. ("CD", [new_evalstack, "prev", evalstack]),
  495. ("CD", [evalstack, "inst", inst]),
  496. ("CD", [evalstack, "phase", new_phase]),
  497. ("DE", [evalstack_link]),
  498. ("DE", [ip_link]),
  499. ]
  500. def assign_value(self, task_root):
  501. task_frame, = yield [("RD", [task_root, "frame"])]
  502. phase_link, evalstack, returnvalue, evalstack_link, ip_link, inst = \
  503. yield [("RDE", [task_frame, "phase"]),
  504. ("RD", [task_frame, "evalstack"]),
  505. ("RD", [task_frame, "returnvalue"]),
  506. ("RDE", [task_frame, "evalstack"]),
  507. ("RDE", [task_frame, "IP"]),
  508. ("RD", [task_frame, "IP"]),
  509. ]
  510. value, new_evalstack, new_phase, evalstack_phase = \
  511. yield [("RD", [inst, "value"]),
  512. ("CN", []),
  513. ("CNV", ["init"]),
  514. ("CNV", ["assign"]),
  515. ]
  516. _, _, _, _, _, _, _, _, _, _ = \
  517. yield [("CD", [task_frame, "variable", returnvalue]),
  518. ("CD", [task_frame, "phase", new_phase]),
  519. ("CD", [task_frame, "evalstack", new_evalstack]),
  520. ("CD", [new_evalstack, "prev", evalstack]),
  521. ("CD", [evalstack, "inst", inst]),
  522. ("CD", [evalstack, "phase", evalstack_phase]),
  523. ("CD", [task_frame, "IP", value]),
  524. ("DE", [evalstack_link]),
  525. ("DE", [phase_link]),
  526. ("DE", [ip_link]),
  527. ]
  528. def assign_assign(self, task_root):
  529. task_frame, = yield [("RD", [task_root, "frame"])]
  530. phase_link, returnvalue, variable_link, variable = \
  531. yield [("RDE", [task_frame, "phase"]),
  532. ("RD", [task_frame, "returnvalue"]),
  533. ("RDE", [task_frame, "variable"]),
  534. ("RD", [task_frame, "variable"]),
  535. ]
  536. value_link, new_phase = \
  537. yield [("RDE", [variable, "value"]),
  538. ("CNV", ["finish"]),
  539. ]
  540. _, _, _, _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  541. ("CD", [variable, "value", returnvalue]),
  542. ("DE", [variable_link]),
  543. ("DE", [value_link]),
  544. ("DE", [phase_link]),
  545. ]
  546. def return_init(self, task_root):
  547. task_frame, = yield [("RD", [task_root, "frame"])]
  548. inst, = yield [("RD", [task_frame, "IP"])]
  549. value, = yield [("RD", [inst, "value"])]
  550. if value is None:
  551. prev_frame, = yield [("RD", [task_frame, "prev"])]
  552. if prev_frame is None:
  553. _, = yield [("DN", [task_root])]
  554. del self.debug_info[self.taskname]
  555. else:
  556. if self.debug_info[self.taskname]:
  557. self.debug_info[self.taskname].pop()
  558. _, _ = yield [("CD", [task_root, "frame", prev_frame]),
  559. ("DN", [task_frame]),
  560. ]
  561. else:
  562. evalstack, evalstack_link, ip_link, new_evalstack, evalstack_phase = \
  563. yield [("RD", [task_frame, "evalstack"]),
  564. ("RDE", [task_frame, "evalstack"]),
  565. ("RDE", [task_frame, "IP"]),
  566. ("CN", []),
  567. ("CNV", ["eval"]),
  568. ]
  569. _, _, _, _, _, _, _ = \
  570. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  571. ("CD", [new_evalstack, "prev", evalstack]),
  572. ("CD", [evalstack, "inst", inst]),
  573. ("CD", [evalstack, "phase", evalstack_phase]),
  574. ("CD", [task_frame, "IP", value]),
  575. ("DE", [evalstack_link]),
  576. ("DE", [ip_link]),
  577. ]
  578. def return_eval(self, task_root):
  579. if self.debug_info[self.taskname]:
  580. self.debug_info[self.taskname].pop()
  581. task_frame, = yield [("RD", [task_root, "frame"])]
  582. prev_frame, = yield [("RD", [task_frame, "prev"])]
  583. if prev_frame is None:
  584. _, = yield [("DN", [task_root])]
  585. del self.debug_info[self.taskname]
  586. else:
  587. returnvalue, old_returnvalue_link = \
  588. yield [("RD", [task_frame, "returnvalue"]),
  589. ("RDE", [prev_frame, "returnvalue"]),
  590. ]
  591. _, _, _, _ = yield [("CD", [task_root, "frame", prev_frame]),
  592. ("CD", [prev_frame, "returnvalue", returnvalue]),
  593. ("DE", [old_returnvalue_link]),
  594. ("DN", [task_frame]),
  595. ]
  596. def constant_init(self, task_root):
  597. task_frame, = yield [("RD", [task_root, "frame"])]
  598. phase_link, returnvalue_link, inst = \
  599. yield [("RDE", [task_frame, "phase"]),
  600. ("RDE", [task_frame, "returnvalue"]),
  601. ("RD", [task_frame, "IP"]),
  602. ]
  603. node, new_phase = yield [("RD", [inst, "node"]),
  604. ("CNV", ["finish"]),
  605. ]
  606. _, _, _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  607. ("CD", [task_frame, "returnvalue", node]),
  608. ("DE", [returnvalue_link]),
  609. ("DE", [phase_link]),
  610. ]
  611. def helper_init(self, task_root):
  612. task_frame, = yield [("RD", [task_root, "frame"])]
  613. inst, = yield [("RD", [task_frame, "IP"])]
  614. next, = yield [("RD", [inst, "next"])]
  615. if next is None:
  616. ip_link, phase_link, evalstack_top = \
  617. yield [("RDE", [task_frame, "IP"]),
  618. ("RDE", [task_frame, "phase"]),
  619. ("RD", [task_frame, "evalstack"]),
  620. ]
  621. evalstack, = yield [("RD", [evalstack_top, "prev"])]
  622. evalstack_inst, evalstack_phase, evalstack_inst_link, evalstack_phase_link = \
  623. yield [("RD", [evalstack, "inst"]),
  624. ("RD", [evalstack, "phase"]),
  625. ("RDE", [evalstack, "inst"]),
  626. ("RDE", [evalstack, "phase"]),
  627. ]
  628. _, _, _, _, _, _, _, _ = \
  629. yield [("CD", [task_frame, "evalstack", evalstack]),
  630. ("CD", [task_frame, "IP", evalstack_inst]),
  631. ("CD", [task_frame, "phase", evalstack_phase]),
  632. ("DE", [ip_link]),
  633. ("DE", [phase_link]),
  634. ("DE", [evalstack_inst_link]),
  635. ("DE", [evalstack_phase_link]),
  636. ("DN", [evalstack_top]),
  637. ]
  638. else:
  639. ip_link, phase_link, new_phase = \
  640. yield [("RDE", [task_frame, "IP"]),
  641. ("RDE", [task_frame, "phase"]),
  642. ("CNV", ["init"]),
  643. ]
  644. _, _, _, _ = yield [("CD", [task_frame, "IP", next]),
  645. ("CD", [task_frame, "phase", new_phase]),
  646. ("DE", [ip_link]),
  647. ("DE", [phase_link]),
  648. ]
  649. def call_init(self, task_root):
  650. task_frame, = yield [("RD", [task_root, "frame"])]
  651. symbols, evalstack, evalstack_link, ip_link, inst = \
  652. yield [("RD", [task_frame, "symbols"]),
  653. ("RD", [task_frame, "evalstack"]),
  654. ("RDE", [task_frame, "evalstack"]),
  655. ("RDE", [task_frame, "IP"]),
  656. ("RD", [task_frame, "IP"]),
  657. ]
  658. func, params = yield [("RD", [inst, "func"]),
  659. ("RD", [inst, "params"]),
  660. ]
  661. if params is None:
  662. new_evalstack, evalstack_phase = \
  663. yield [("CN", []),
  664. ("CNV", ["call"]),
  665. ]
  666. _, _, _, _, _, _, _ = \
  667. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  668. ("CD", [new_evalstack, "prev", evalstack]),
  669. ("CD", [evalstack, "inst", inst]),
  670. ("CD", [evalstack, "phase", evalstack_phase]),
  671. ("CD", [task_frame, "IP", func]),
  672. ("DE", [evalstack_link]),
  673. ("DE", [ip_link]),
  674. ]
  675. else:
  676. new_evalstack,= yield [("CN", [])]
  677. _, _, _, _, _, _, _ = \
  678. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  679. ("CD", [new_evalstack, "prev", evalstack]),
  680. ("CD", [evalstack, "inst", inst]),
  681. ("CD", [evalstack, "phase", params]),
  682. ("CD", [task_frame, "IP", func]),
  683. ("DE", [evalstack_link]),
  684. ("DE", [ip_link]),
  685. ]
  686. def call_call(self, task_root):
  687. self.debug_info[self.taskname].append("None")
  688. task_frame, = yield [("RD", [task_root, "frame"])]
  689. inst, = yield [("RD", [task_frame, "IP"])]
  690. param, = yield [("RD", [inst, "last_param"])]
  691. if param is None:
  692. returnvalue, = yield [("RD", [task_frame, "returnvalue"])]
  693. body, phase_link, frame_link, prev_phase, new_phase, new_frame, new_evalstack, new_symbols, new_returnvalue = \
  694. yield [("RD", [returnvalue, "body"]),
  695. ("RDE", [task_frame, "phase"]),
  696. ("RDE", [task_root, "frame"]),
  697. ("CNV", ["finish"]),
  698. ("CNV", ["init"]),
  699. ("CN", []),
  700. ("CN", []),
  701. ("CN", []),
  702. ("CN", []),
  703. ]
  704. _, _, _, _, _, _, _, _, _, _, _ = \
  705. yield [("CD", [task_root, "frame", new_frame]),
  706. ("CD", [new_frame, "evalstack", new_evalstack]),
  707. ("CD", [new_frame, "symbols", new_symbols]),
  708. ("CD", [new_frame, "returnvalue", new_returnvalue]),
  709. ("CD", [new_frame, "caller", inst]),
  710. ("CD", [new_frame, "phase", new_phase]),
  711. ("CD", [new_frame, "IP", body]),
  712. ("CD", [new_frame, "prev", task_frame]),
  713. ("CD", [task_frame, "phase", prev_phase]),
  714. ("DE", [phase_link]),
  715. ("DE", [frame_link]),
  716. ]
  717. else:
  718. newer_frames, invoking_frames = \
  719. yield [("RRD", [task_frame, "prev"]),
  720. ("RRD", [inst, "caller"]),
  721. ]
  722. new_frame = self.find_overlapping(newer_frames, invoking_frames)
  723. phase_link, frame_link, new_symbols, new_IP = \
  724. yield [("RDE", [task_frame, "phase"]),
  725. ("RDE", [task_root, "frame"]),
  726. ("RD", [new_frame, "symbols"]),
  727. ("RD", [new_frame, "IP"]),
  728. ]
  729. signature, = yield [("RRD", [new_IP, "body"])]
  730. signature = signature[0]
  731. sig_params, last_param = \
  732. yield [("RD", [signature, "params"]),
  733. ("RD", [inst, "last_param"]),
  734. ]
  735. name, = yield [("RD", [last_param, "name"])]
  736. name_value, = yield [("RV", [name])]
  737. returnvalue, formal_parameter, new_phase, variable = \
  738. yield [("RD", [task_frame, "returnvalue"]),
  739. ("RD", [sig_params, name_value]),
  740. ("CNV", ["finish"]),
  741. ("CN", []),
  742. ]
  743. _, _, _, t1 = yield [("CD", [task_root, "frame", new_frame]),
  744. ("CD", [task_frame, "phase", new_phase]),
  745. ("CD", [variable, "value", returnvalue]),
  746. ("CE", [new_symbols, variable]),
  747. ]
  748. _, _, _ = yield [("CE", [t1, formal_parameter]),
  749. ("DE", [frame_link]),
  750. ("DE", [phase_link]),
  751. ]
  752. def find_overlapping(self, a, b):
  753. newer_frames = set(a)
  754. invoking_frames = set(b)
  755. matches = list(newer_frames.intersection(invoking_frames))
  756. if len(matches) == 1:
  757. return matches[0]
  758. elif len(matches) > 1:
  759. raise Exception("Error: multiple overlapping elements")
  760. else:
  761. raise Exception("Error: could not find any overlap")
  762. def call_param(self, task_root):
  763. task_frame, = yield [("RD", [task_root, "frame"])]
  764. inst, phase = yield [("RD", [task_frame, "IP"]),
  765. ("RD", [task_frame, "phase"]),
  766. ]
  767. params, last_param = \
  768. yield [("RD", [inst, "params"]),
  769. ("RD", [inst, "last_param"]),
  770. ]
  771. next_param, = yield [("RD", [params, "next_param"])]
  772. if params == phase:
  773. phase_link, ip_link, returnvalue, param_value, evalstack, evalstack_link = \
  774. yield [("RDE", [task_frame, "phase"]),
  775. ("RDE", [task_frame, "IP"]),
  776. ("RD", [task_frame, "returnvalue"]),
  777. ("RD", [params, "value"]),
  778. ("RD", [task_frame, "evalstack"]),
  779. ("RDE", [task_frame, "evalstack"]),
  780. ]
  781. body, = yield [("RD", [returnvalue, "body"])]
  782. new_frame, prev_evalstack, new_phase, prev_phase, new_evalstack, new_symbols, new_returnvalue = \
  783. yield [("CN", []),
  784. ("CN", []),
  785. ("CNV", ["init"]),
  786. ("CNV", ["init"]),
  787. ("CN", []),
  788. ("CN", []),
  789. ("CN", []),
  790. ]
  791. _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = \
  792. yield [("CD", [new_frame, "evalstack", new_evalstack]),
  793. ("CD", [new_frame, "symbols", new_symbols]),
  794. ("CD", [new_frame, "returnvalue", new_returnvalue]),
  795. ("CD", [new_frame, "caller", inst]),
  796. ("CD", [new_frame, "phase", new_phase]),
  797. ("CD", [new_frame, "IP", body]),
  798. ("CD", [new_frame, "prev", task_frame]),
  799. ("CD", [task_frame, "phase", prev_phase]),
  800. ("CD", [task_frame, "IP", param_value]),
  801. ("CD", [prev_evalstack, "prev", evalstack]),
  802. ("CD", [evalstack, "inst", inst]),
  803. ("CD", [task_frame, "evalstack", prev_evalstack]),
  804. ("DE", [evalstack_link]),
  805. ("DE", [ip_link]),
  806. ("DE", [phase_link]),
  807. ]
  808. if next_param is not None:
  809. _ = yield [("CD", [evalstack, "phase", next_param])]
  810. else:
  811. evalstack_phase, = \
  812. yield [("CNV", ["call"])]
  813. _ = yield [("CD", [evalstack, "phase", evalstack_phase])]
  814. else:
  815. frame_link, phase_link, newer_frames, invoking_frames = \
  816. yield [("RDE", [task_root, "frame"]),
  817. ("RDE", [task_frame, "phase"]),
  818. ("RRD", [task_frame, "prev"]),
  819. ("RRD", [inst, "caller"]),
  820. ]
  821. new_frame = self.find_overlapping(newer_frames, invoking_frames)
  822. ip_link, evalstack, evalstack_link, new_symbols, new_IP = \
  823. yield [("RDE", [task_frame, "IP"]),
  824. ("RD", [task_frame, "evalstack"]),
  825. ("RDE", [task_frame, "evalstack"]),
  826. ("RD", [new_frame, "symbols"]),
  827. ("RD", [new_frame, "IP"]),
  828. ]
  829. signature, = yield [("RRD", [new_IP, "body"])]
  830. signature = signature[0]
  831. sig_params, = yield [("RD", [signature, "params"])]
  832. if last_param == phase:
  833. prev_param, = \
  834. yield [("RRD", [last_param, "next_param"])]
  835. prev_param = prev_param[0]
  836. name, = yield [("RD", [prev_param, "name"])]
  837. name_value, = \
  838. yield [("RV", [name])]
  839. evalstack_phase, = \
  840. yield [("CNV", ["call"])]
  841. _ = yield [("CD", [evalstack, "phase", evalstack_phase])]
  842. formal_parameter, param_value = \
  843. yield [("RD", [sig_params, name_value]),
  844. ("RD", [last_param, "value"]),
  845. ]
  846. else:
  847. param_b, = yield [("RD", [task_frame, "phase"])]
  848. param_c, param_a = \
  849. yield [("RD", [param_b, "next_param"]),
  850. ("RRD", [param_b, "next_param"]),
  851. ]
  852. param_a = param_a[0]
  853. name, param_value = \
  854. yield [("RD", [param_a, "name"]),
  855. ("RD", [param_b, "value"]),
  856. ]
  857. name_value, = \
  858. yield [("RV", [name])]
  859. formal_parameter, _ = \
  860. yield [("RD", [sig_params, name_value]),
  861. ("CD", [evalstack, "phase", param_c]),
  862. ]
  863. new_phase, new_evalstack, variable, returnvalue = \
  864. yield [("CNV", ["init"]),
  865. ("CN", []),
  866. ("CN", []),
  867. ("RD", [task_frame, "returnvalue"]),
  868. ]
  869. _, _, _, _, _, _ = \
  870. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  871. ("CD", [new_evalstack, "prev", evalstack]),
  872. ("CD", [evalstack, "inst", inst]),
  873. ("CD", [task_frame, "phase", new_phase]),
  874. ("CD", [task_frame, "IP", param_value]),
  875. ("CD", [variable, "value", returnvalue]),
  876. ]
  877. t1, = yield [("CE", [new_symbols, variable])]
  878. _, _, _, _ = \
  879. yield [("CE", [t1, formal_parameter]),
  880. ("DE", [phase_link]),
  881. ("DE", [ip_link]),
  882. ("DE", [evalstack_link]),
  883. ]
  884. def input_init(self, task_root):
  885. task_frame, = yield [("RD", [task_root, "frame"])]
  886. returnvalue_link, _input = \
  887. yield [("RDE", [task_frame, "returnvalue"]),
  888. ("RD", [task_root, "input"]),
  889. ]
  890. value, next, phase_link = \
  891. yield [("RD", [_input, "value"]),
  892. ("RD", [_input, "next"]),
  893. ("RDE", [task_frame, "phase"]),
  894. ]
  895. if value is not None:
  896. v = yield [("RV", [value])]
  897. _, _, finish = \
  898. yield [("CD", [task_frame, "returnvalue", value]),
  899. ("CD", [task_root, "input", next]),
  900. ("CNV", ["finish"]),
  901. ]
  902. _, _, _, _ = \
  903. yield [("CD", [task_frame, "phase", finish]),
  904. ("DN", [_input]),
  905. ("DE", [returnvalue_link]),
  906. ("DE", [phase_link]),
  907. ]
  908. self.input_value = value
  909. else:
  910. # No input yet, so just wait and don't advance IP or phase
  911. self.input_value = None
  912. self.success = False
  913. def output_init(self, task_root):
  914. task_frame, = yield [("RD", [task_root, "frame"])]
  915. evalstack, evalstack_link, ip_link, inst = \
  916. yield [("RD", [task_frame, "evalstack"]),
  917. ("RDE", [task_frame, "evalstack"]),
  918. ("RDE", [task_frame, "IP"]),
  919. ("RD", [task_frame, "IP"]),
  920. ]
  921. value, new_evalstack, evalstack_phase = \
  922. yield [("RD", [inst, "value"]),
  923. ("CN", []),
  924. ("CNV", ["output"]),
  925. ]
  926. _, _, _, _, _, _, _ = \
  927. yield [("CD", [task_frame, "evalstack", new_evalstack]),
  928. ("CD", [new_evalstack, "prev", evalstack]),
  929. ("CD", [evalstack, "inst", inst]),
  930. ("CD", [evalstack, "phase", evalstack_phase]),
  931. ("CD", [task_frame, "IP", value]),
  932. ("DE", [evalstack_link]),
  933. ("DE", [ip_link]),
  934. ]
  935. def output_output(self, task_root):
  936. task_frame, = yield [("RD", [task_root, "frame"])]
  937. returnvalue_link, returnvalue, last_output, phase_link, last_output_link, new_last_output, finish = \
  938. yield [("RDE", [task_frame, "returnvalue"]),
  939. ("RD", [task_frame, "returnvalue"]),
  940. ("RD", [task_root, "last_output"]),
  941. ("RDE", [task_frame, "phase"]),
  942. ("RDE", [task_root, "last_output"]),
  943. ("CN", []),
  944. ("CNV", ["finish"]),
  945. ]
  946. _, _, _, _, _, _ = \
  947. yield [("CD", [last_output, "value", returnvalue]),
  948. ("CD", [last_output, "next", new_last_output]),
  949. ("CD", [task_root, "last_output", new_last_output]),
  950. ("CD", [task_frame, "phase", finish]),
  951. ("DE", [last_output_link]),
  952. ("DE", [phase_link]),
  953. ]
  954. def declare_init(self, task_root):
  955. task_frame, = yield [("RD", [task_root, "frame"])]
  956. inst, = yield [("RD", [task_frame, "IP"])]
  957. new_var, symbols, phase_link, empty_node, new_phase = \
  958. yield [("RD", [inst, "var"]),
  959. ("RD", [task_frame, "symbols"]),
  960. ("RDE", [task_frame, "phase"]),
  961. ("CN", []),
  962. ("CNV", ["finish"]),
  963. ]
  964. exists, = yield [("RDN", [symbols, new_var])]
  965. if exists is None:
  966. new_edge, = yield [("CE", [symbols, empty_node])]
  967. _ = yield [("CE", [new_edge, new_var])]
  968. _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  969. ("DE", [phase_link]),
  970. ]
  971. def global_init(self, task_root):
  972. task_frame, = yield [("RD", [task_root, "frame"])]
  973. inst, = yield [("RD", [task_frame, "IP"])]
  974. new_var, global_symbols, phase_link, empty_node, new_phase = \
  975. yield [("RD", [inst, "var"]),
  976. ("RD", [task_root, "globals"]),
  977. ("RDE", [task_frame, "phase"]),
  978. ("CN", []),
  979. ("CNV", ["finish"]),
  980. ]
  981. value, = yield [("RV", [new_var])]
  982. exists, = yield [("RD", [global_symbols, value])]
  983. if exists is None:
  984. yield [("CD", [global_symbols, value, empty_node])]
  985. _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  986. ("DE", [phase_link])
  987. ]