|
@@ -11,16 +11,18 @@ def interpret_function(function_id, named_arguments, **kwargs):
|
|
body_id, = yield [("RD", [function_id, "body"])]
|
|
body_id, = yield [("RD", [function_id, "body"])]
|
|
|
|
|
|
# Create a new stack frame.
|
|
# Create a new stack frame.
|
|
- frame_link, new_phase, new_frame, new_evalstack, new_symbols, new_returnvalue = \
|
|
|
|
|
|
+ frame_link, new_phase, new_frame, new_evalstack, new_symbols, \
|
|
|
|
+ new_returnvalue, intrinsic_return = \
|
|
yield [("RDE", [user_root, "frame"]),
|
|
yield [("RDE", [user_root, "frame"]),
|
|
("CNV", ["init"]),
|
|
("CNV", ["init"]),
|
|
("CN", []),
|
|
("CN", []),
|
|
("CN", []),
|
|
("CN", []),
|
|
("CN", []),
|
|
("CN", []),
|
|
("CN", []),
|
|
("CN", []),
|
|
|
|
+ ("CN", [])
|
|
]
|
|
]
|
|
|
|
|
|
- _, _, _, _, _, _, _, _, _ = \
|
|
|
|
|
|
+ _, _, _, _, _, _, _, _, _, _ = \
|
|
yield [("CD", [user_root, "frame", new_frame]),
|
|
yield [("CD", [user_root, "frame", new_frame]),
|
|
("CD", [new_frame, "evalstack", new_evalstack]),
|
|
("CD", [new_frame, "evalstack", new_evalstack]),
|
|
("CD", [new_frame, "symbols", new_symbols]),
|
|
("CD", [new_frame, "symbols", new_symbols]),
|
|
@@ -29,7 +31,11 @@ def interpret_function(function_id, named_arguments, **kwargs):
|
|
("CD", [new_frame, "phase", new_phase]),
|
|
("CD", [new_frame, "phase", new_phase]),
|
|
("CD", [new_frame, "IP", body_id]),
|
|
("CD", [new_frame, "IP", body_id]),
|
|
("CD", [new_frame, "prev", user_frame]),
|
|
("CD", [new_frame, "prev", user_frame]),
|
|
- ("DE", [frame_link]),
|
|
|
|
|
|
+ ("CD", [
|
|
|
|
+ new_frame,
|
|
|
|
+ primitive_functions.PRIMITIVE_RETURN_KEY,
|
|
|
|
+ intrinsic_return]),
|
|
|
|
+ ("DE", [frame_link])
|
|
]
|
|
]
|
|
|
|
|
|
# Put the parameters in the new stack frame's symbol table.
|
|
# Put the parameters in the new stack frame's symbol table.
|
|
@@ -58,19 +64,6 @@ def interpret_function(function_id, named_arguments, **kwargs):
|
|
while 1:
|
|
while 1:
|
|
inp = yield gen.send(inp)
|
|
inp = yield gen.send(inp)
|
|
except StopIteration:
|
|
except StopIteration:
|
|
- # An instruction has been completed. Check if we've already returned.
|
|
|
|
- #
|
|
|
|
- # TODO: the statement below performs O(n) state reads whenever an instruction
|
|
|
|
- # finishes, where n is the number of 'interpret_function' stack frames.
|
|
|
|
- # I don't *think* that this is problematic (at least not in the short term),
|
|
|
|
- # but an O(1) solution would obviously be much better; that's the interpreter's
|
|
|
|
- # complexity. Perhaps we can annotate the stack frame we create here with a marker
|
|
|
|
- # that the kernel can pick up on? We could have the kernel throw an exception whenever
|
|
|
|
- # it encounters said marker.
|
|
|
|
- current_user_frame, = yield [("RD", [user_root, "frame"])]
|
|
|
|
- if current_user_frame == user_frame:
|
|
|
|
- # We're done here. Extract the return value and get out.
|
|
|
|
- returnvalue, = yield [("RD", [user_frame, "returnvalue"])]
|
|
|
|
- raise primitive_functions.PrimitiveFinished(returnvalue)
|
|
|
|
- else:
|
|
|
|
- yield None
|
|
|
|
|
|
+ # An instruction has been completed. Forward it.
|
|
|
|
+ yield None
|
|
|
|
+ # Let primitive_functions.PrimitiveFinished bubble up.
|