Skip to main content

devela/lang/prog/script/machine/
call.rs

1// devela/src/lang/prog/script/machine/call.rs
2//
3//!
4//
5
6#[cfg(doc)]
7use crate::ScriptMachine;
8use crate::{ConstInit, InvalidValue, NonMaxU16, WordTry, unwrap};
9
10#[doc = crate::_tags!(lang uid)]
11/// A compact contextual identifier for a host operation.
12#[doc = crate::_doc_meta!{
13    location("lang/prog/script/machine"),
14    test_size_of(ScriptCallId = 2|16; niche Option),
15}]
16#[must_use]
17#[repr(transparent)]
18#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct ScriptCallId(NonMaxU16);
20
21impl ConstInit for ScriptCallId {
22    /// Uses the largest representable identifier as a conspicuous initializer.
23    ///
24    /// This value is not reserved and may still be assigned meaning by a host.
25    const INIT: Self = Self(NonMaxU16::MAX);
26}
27
28impl ScriptCallId {
29    /// Constructs a host-call identifier from its raw value.
30    #[must_use]
31    pub const fn new(raw: u16) -> Option<Self> {
32        Some(Self(unwrap![some? NonMaxU16::new(raw)]))
33    }
34    // MAYBE pub const fn from_repr(raw: NonMaxU16) -> Self { Self(raw) }
35
36    /// Returns the raw identifier value.
37    #[must_use]
38    pub const fn raw(self) -> u16 {
39        self.0.get()
40    }
41}
42
43impl WordTry for ScriptCallId {
44    type Repr = u16;
45    type Error = InvalidValue;
46    fn raw(self) -> Self::Repr {
47        ScriptCallId::raw(self)
48    }
49    fn try_from_raw(raw: Self::Repr) -> Result<Self, Self::Error> {
50        unwrap![some_ok_or ScriptCallId::new(raw), InvalidValue]
51    }
52}
53
54#[doc = crate::_tags!(lang runtime)]
55/// A host operation awaiting resolution by the caller.
56#[doc = crate::_doc_meta!{
57    location("lang/prog/script/machine"),
58    #[cfg(target_pointer_width = "32")]
59    test_size_of(ScriptCall = 12|96; niche Option),
60    #[cfg(target_pointer_width = "64")]
61    test_size_of(ScriptCall = 24|192; niche Option),
62}]
63/// A call remains valid while the originating machine is left unchanged.
64/// It may be inspected and then completed with [`ScriptMachine::complete_call`].
65#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
66pub struct ScriptCall {
67    pub(super) ip: usize,
68    pub(super) stack_len: usize,
69    id: ScriptCallId,
70    arity: u8,
71}
72impl ConstInit for ScriptCall {
73    /// An inactive call token that cannot match a valid machine state.
74    const INIT: Self = Self {
75        ip: usize::MAX,
76        stack_len: usize::MAX,
77        id: ScriptCallId::INIT,
78        arity: u8::MAX,
79    };
80}
81impl ScriptCall {
82    pub(crate) const fn new(ip: usize, stack_len: usize, id: ScriptCallId, arity: u8) -> Self {
83        Self { ip, stack_len, id, arity }
84    }
85    /// Returns the host-operation identifier.
86    pub const fn id(self) -> ScriptCallId {
87        self.id
88    }
89    /// Returns the number of arguments supplied to the call.
90    #[must_use]
91    pub const fn arity(self) -> u8 {
92        self.arity
93    }
94    /// Returns the instruction position requesting the call.
95    #[must_use]
96    pub const fn ip(self) -> usize {
97        self.ip
98    }
99}