runtime.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import modelverse_kernel.primitives as primitive_functions
  2. class JitCompilationFailedException(Exception):
  3. """A type of exception that is raised when the jit fails to compile a function."""
  4. pass
  5. def call_function(function_id, named_arguments, **kwargs):
  6. """Makes the interpreter run the function with the given id with the specified
  7. argument dictionary."""
  8. user_root = kwargs['user_root']
  9. kernel = kwargs['mvk']
  10. body_id, = yield [("RD", [function_id, "body"])]
  11. kernel.jit.mark_entry_point(body_id)
  12. # Try to jit the function here. We might be able to avoid building the stack
  13. # frame.
  14. def handle_jit_failed(_):
  15. interpreter_args = {'body_id' : body_id, 'named_arguments' : named_arguments}
  16. interpreter_args.update(kwargs)
  17. yield [("TAIL_CALL_KWARGS", [interpret_function, interpreter_args])]
  18. yield [("TRY", [])]
  19. yield [("CATCH", [JitCompilationFailedException, handle_jit_failed])]
  20. # Try to compile.
  21. compiled_func, = yield [("CALL_ARGS", [kernel.jit_compile, (user_root, body_id)])]
  22. yield [("END_TRY", [])]
  23. # Add the keyword arguments to the argument dictionary.
  24. named_arguments.update(kwargs)
  25. # Run the function.
  26. yield [("TAIL_CALL_KWARGS", [compiled_func, named_arguments])]
  27. def interpret_function(body_id, named_arguments, **kwargs):
  28. """Makes the interpreter run the function with the given id with the specified
  29. argument dictionary."""
  30. user_root = kwargs['user_root']
  31. kernel = kwargs['mvk']
  32. user_frame, = yield [("RD", [user_root, "frame"])]
  33. inst, = yield [("RD", [user_frame, "IP"])]
  34. # Create a new stack frame.
  35. frame_link, new_phase, new_frame, new_evalstack, new_symbols, \
  36. new_returnvalue, intrinsic_return = \
  37. yield [("RDE", [user_root, "frame"]),
  38. ("CNV", ["init"]),
  39. ("CN", []),
  40. ("CN", []),
  41. ("CN", []),
  42. ("CN", []),
  43. ("CN", [])
  44. ]
  45. _, _, _, _, _, _, _, _, _, _ = \
  46. yield [("CD", [user_root, "frame", new_frame]),
  47. ("CD", [new_frame, "evalstack", new_evalstack]),
  48. ("CD", [new_frame, "symbols", new_symbols]),
  49. ("CD", [new_frame, "returnvalue", new_returnvalue]),
  50. ("CD", [new_frame, "caller", inst]),
  51. ("CD", [new_frame, "phase", new_phase]),
  52. ("CD", [new_frame, "IP", body_id]),
  53. ("CD", [new_frame, "prev", user_frame]),
  54. ("CD", [
  55. new_frame,
  56. primitive_functions.EXCEPTION_RETURN_KEY,
  57. intrinsic_return]),
  58. ("DE", [frame_link])
  59. ]
  60. # Put the parameters in the new stack frame's symbol table.
  61. (parameter_vars, parameter_names), = yield [
  62. ("CALL_ARGS", [kernel.jit.jit_parameters, (body_id,)])]
  63. parameter_dict = dict(zip(parameter_names, parameter_vars))
  64. for (key, value) in named_arguments.items():
  65. param_var = parameter_dict[key]
  66. variable, = yield [("CN", [])]
  67. yield [("CD", [variable, "value", value])]
  68. symbol_edge, = yield [("CE", [new_symbols, variable])]
  69. yield [("CE", [symbol_edge, param_var])]
  70. username = kwargs['username']
  71. def exception_handler(ex):
  72. print('Returning from interpreted function. Result: %s' % ex.result)
  73. raise primitive_functions.PrimitiveFinished(ex.result)
  74. # Create an exception handler to catch and translate InterpretedFunctionFinished.
  75. yield [("TRY", [])]
  76. yield [("CATCH", [primitive_functions.InterpretedFunctionFinished, exception_handler])]
  77. while 1:
  78. result, = yield [("CALL_ARGS", [kernel.execute_rule, (username,)])]
  79. # An instruction has completed. Forward it.
  80. yield result
  81. def get_input(**parameters):
  82. """Retrieves input."""
  83. mvk = parameters["mvk"]
  84. user_root = parameters["user_root"]
  85. while 1:
  86. yield [("CALL_ARGS", [mvk.input_init, (user_root,)])]
  87. # Finished
  88. if mvk.success:
  89. # Got some input, so we can access it
  90. raise primitive_functions.PrimitiveFinished(mvk.input_value)
  91. else:
  92. # No input, so yield None but don't stop
  93. yield None