main.py 59 KB

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