Skip to main content

aranya_policy_module/
instructions.rs

1use core::{
2    fmt::{self, Display},
3    num::NonZeroUsize,
4};
5
6use aranya_policy_ast::Identifier;
7use serde::{Deserialize, Serialize};
8
9mod meta;
10
11pub use meta::*;
12
13use crate::{Label, data::Value};
14
15/// Reason for ending execution.
16#[must_use]
17#[derive(
18    Clone,
19    Debug,
20    Eq,
21    PartialEq,
22    Serialize,
23    Deserialize,
24    rkyv::Archive,
25    rkyv::Deserialize,
26    rkyv::Serialize,
27)]
28pub enum ExitReason {
29    /// Execution completed without errors.
30    Normal,
31    /// Execution is paused to return a result, which is at the top of the stack. Call `RunState::run()` again to resume.
32    Yield,
33    /// Execution was aborted gracefully, due an error.
34    Check,
35    /// Execution was aborted due to an unhandled error.
36    Panic,
37}
38
39impl ExitReason {
40    /// Asserts that the reason is `ExitReason::Normal`.
41    #[cfg(feature = "testing")]
42    pub fn success(self) {
43        assert_eq!(self, Self::Normal);
44    }
45}
46
47impl Display for ExitReason {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        match self {
50            Self::Normal => f.write_str("normal"),
51            Self::Yield => f.write_str("yield"),
52            Self::Check => f.write_str("check"),
53            Self::Panic => f.write_str("panic"),
54        }
55    }
56}
57
58/// The target of a branch
59#[derive(
60    Debug,
61    Clone,
62    Eq,
63    PartialEq,
64    Serialize,
65    Deserialize,
66    rkyv::Archive,
67    rkyv::Deserialize,
68    rkyv::Serialize,
69)]
70pub enum Target {
71    /// An unresolved target with a symbolic name
72    Unresolved(Label),
73    /// A resolved target referring to an address
74    Resolved(usize),
75}
76
77impl Target {
78    /// Get the resolved address or None if it has not been resolved.
79    pub fn resolved(&self) -> Option<usize> {
80        match self {
81            Self::Resolved(i) => Some(*i),
82            Self::Unresolved(_) => None,
83        }
84    }
85}
86
87impl Display for Target {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        match self {
90            Self::Unresolved(label) => write!(f, "<{label}>"),
91            Self::Resolved(addr) => write!(f, "{addr}"),
92        }
93    }
94}
95
96/// The machine instruction types
97#[derive(
98    Debug,
99    Clone,
100    Eq,
101    PartialEq,
102    Serialize,
103    Deserialize,
104    rkyv::Archive,
105    rkyv::Deserialize,
106    rkyv::Serialize,
107)]
108pub enum Instruction {
109    // data
110    /// Push a value onto the stack
111    Const(Value),
112    /// Define a local value by name
113    Def(Identifier),
114    /// Get a local value by name
115    Get(Identifier),
116    /// Duplicate the value at the top of the stack
117    Dup,
118    /// Remove a value from the top of the stack
119    Pop,
120    // control flow
121    /// Define the beginning of a block
122    Block,
123    /// Define the end of a block
124    End,
125    /// Jump forward to the target in the current block
126    Jump(Target),
127    /// Jump if top of stack is true
128    Branch(Target),
129    /// Jump to the beginning of the block
130    Next,
131    /// Jump to the end of the block
132    Last,
133    /// Call regular function at target
134    Call(Target),
135    /// Call external function (FFI), specified by module, procedure indices. The FFI modules should be added to the MachineIO.
136    ExtCall(usize, usize),
137    /// Return to the last address on the control flow stack
138    Return,
139    /// End execution non-fatally
140    Exit(ExitReason),
141    // arithmetic/logic
142    /// Add two numbers
143    Add,
144    /// Subtract two numbers
145    Sub,
146    /// Add two numbers with saturation
147    SaturatingAdd,
148    /// Subtract two numbers with saturation
149    SaturatingSub,
150    /// Logical negation
151    Not,
152    /// Greater than
153    Gt,
154    /// Less than
155    Lt,
156    /// Equality
157    Eq,
158    // facts
159    /// Create a fact object by name
160    FactNew(Identifier),
161    /// Set a key member
162    FactKeySet(Identifier),
163    /// Set a value member
164    FactValueSet(Identifier),
165    // structs
166    /// Create a struct object by name
167    StructNew(Identifier),
168    /// Add a member to the struct
169    StructSet(Identifier),
170    /// Get a member from the struct
171    StructGet(Identifier),
172    /// Add multiple members to the struct
173    MStructSet(NonZeroUsize),
174    /// Get multiple members from the struct
175    MStructGet(NonZeroUsize),
176    /// Cast previous stack value to given type
177    Cast(Identifier),
178    // context-specific
179    /// Publish a struct as a command
180    Publish,
181    /// Create a fact
182    Create,
183    /// Delete a fact
184    Delete,
185    /// Update a fact
186    Update,
187    /// Emit an effect
188    Emit,
189    /// Query for a fact
190    Query,
191    /// Count facts, up to a given limit
192    FactCount(i64),
193    /// Execute a fact query, and retain results so they can be consumed with `QueryNext`.
194    QueryStart,
195    /// Fetches the next result, and pushes it onto the stack
196    QueryNext(Identifier),
197    /// Serialize a command struct
198    Serialize,
199    /// Deserialize a command struct
200    Deserialize,
201    /// Save the stack depth for later restoration.
202    SaveSP,
203    /// Restore the stack depth.
204    RestoreSP,
205    /// Wrap value in `Some`
206    Some,
207    /// Unwrap `Some` value
208    Unwrap,
209    /// Metadata for tracing
210    Meta(Meta),
211}
212
213impl Display for Instruction {
214    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215        match self {
216            Self::Const(v) => write!(f, "const {v}"),
217            Self::Def(ident) => write!(f, "def {ident}"),
218            Self::Get(ident) => write!(f, "get {ident}"),
219            Self::Dup => write!(f, "dup"),
220            Self::Pop => write!(f, "pop"),
221            Self::Block => write!(f, "block"),
222            Self::End => write!(f, "end"),
223            Self::Jump(t) => write!(f, "jump {t}"),
224            Self::Branch(t) => write!(f, "branch {t}"),
225            Self::Next => write!(f, "next"),
226            Self::Last => write!(f, "last"),
227            Self::Call(t) => write!(f, "call {t}"),
228            Self::ExtCall(module, proc) => write!(f, "extcall {module} {proc}"),
229            Self::Return => write!(f, "return"),
230            Self::Exit(reason) => write!(f, "exit {reason}"),
231            Self::Add => write!(f, "add"),
232            Self::Sub => write!(f, "sub"),
233            Self::SaturatingAdd => write!(f, "saturating_add"),
234            Self::SaturatingSub => write!(f, "saturating_sub"),
235            Self::Not => write!(f, "not"),
236            Self::Gt => write!(f, "gt"),
237            Self::Lt => write!(f, "lt"),
238            Self::Eq => write!(f, "eq"),
239            Self::FactNew(ident) => write!(f, "fact.new {ident}"),
240            Self::FactKeySet(ident) => write!(f, "fact.kset {ident}"),
241            Self::FactValueSet(ident) => write!(f, "fact.vset {ident}"),
242            Self::StructNew(ident) => write!(f, "struct.new {ident}"),
243            Self::StructSet(ident) => write!(f, "struct.set {ident}"),
244            Self::StructGet(ident) => write!(f, "struct.get {ident}"),
245            Self::MStructGet(n) => write!(f, "mstruct.get {n}"),
246            Self::MStructSet(n) => write!(f, "mstruct.set {n}"),
247            Self::Publish => write!(f, "publish"),
248            Self::Create => write!(f, "create"),
249            Self::Delete => write!(f, "delete"),
250            Self::Update => write!(f, "update"),
251            Self::Emit => write!(f, "emit"),
252            Self::Query => write!(f, "query"),
253            Self::FactCount(limit) => write!(f, "fact.count {limit}"),
254            Self::QueryStart => write!(f, "query.start"),
255            Self::QueryNext(ident) => write!(f, "query.next {ident}"),
256            Self::Serialize => write!(f, "serialize"),
257            Self::Deserialize => write!(f, "deserialize"),
258            Self::SaveSP => write!(f, "save SP"),
259            Self::RestoreSP => write!(f, "restore SP"),
260            Self::Some => write!(f, "some"),
261            Self::Unwrap => write!(f, "unwrap"),
262            Self::Meta(m) => write!(f, "meta: {m}"),
263            Self::Cast(identifier) => write!(f, "cast {identifier}"),
264        }
265    }
266}