legacy.py 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  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 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 [("RDE", [global_symbols, value])]
  983. if exists is not None:
  984. yield [("DE", [exists])]
  985. yield [("CD", [global_symbols, value, empty_node])]
  986. _, _ = yield [("CD", [task_frame, "phase", new_phase]),
  987. ("DE", [phase_link])
  988. ]