monty_types/results.rs
1//! Host-supplied results fed back into a suspended run:
2//! [`NameLookupResult`] and [`ExtFunctionResult`].
3
4use crate::{exceptions::MontyException, object::MontyObject};
5/// Result of a name lookup from the host.
6///
7/// When the VM encounters an unresolved name (or a lazy attribute on a
8/// host-backed object), the host provides one of these:
9/// - `Value(obj)`: The name resolves to this value (a plain name is cached in
10/// its namespace slot; an attribute is re-consulted on every access).
11/// - `Undefined`: The name does not exist — `NameError` for a plain name,
12/// `AttributeError` for an attribute.
13/// - `Error(exc)`: Resolving it raised on the host — the exception is raised
14/// inside the sandbox, so `hasattr()` / `getattr()` defaults do not apply.
15#[derive(Debug)]
16pub enum NameLookupResult {
17 /// The name resolves to this value.
18 Value(MontyObject),
19 /// The name is undefined — the VM raises `NameError` / `AttributeError`.
20 Undefined,
21 /// Resolving the name raised this exception on the host; the VM raises
22 /// it where the lookup suspended, like a failed external call.
23 Error(MontyException),
24}
25
26impl From<MontyObject> for NameLookupResult {
27 fn from(value: MontyObject) -> Self {
28 Self::Value(value)
29 }
30}
31
32impl From<Option<MontyObject>> for NameLookupResult {
33 /// `Some` resolves the name, `None` leaves it undefined.
34 fn from(value: Option<MontyObject>) -> Self {
35 value.map_or(Self::Undefined, Self::Value)
36 }
37}
38
39impl From<MontyException> for NameLookupResult {
40 fn from(exception: MontyException) -> Self {
41 Self::Error(exception)
42 }
43}
44
45/// Return value or exception from an external function.
46#[derive(Debug)]
47pub enum ExtFunctionResult {
48 /// Continues execution with the return value from the external function.
49 Return(MontyObject),
50 /// Continues execution with the exception raised by the external function.
51 Error(MontyException),
52 /// Pending future — the external function is a coroutine.
53 ///
54 /// The `u32` is the `call_id` from the `FunctionCall` that created this
55 /// snapshot. It is used to track the pending future so it can be resolved
56 /// later via `ResolveFutures::resume()`.
57 Future(u32),
58 /// Raises `NameError`, or `ModuleNotFoundError` for an `import` call.
59 NotFound(String),
60}
61
62impl From<MontyObject> for ExtFunctionResult {
63 fn from(value: MontyObject) -> Self {
64 Self::Return(value)
65 }
66}
67
68impl From<MontyException> for ExtFunctionResult {
69 fn from(exception: MontyException) -> Self {
70 Self::Error(exception)
71 }
72}