From 52a25a4516cfbbae70f137b6aec9191f9fc1cf8a Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Fri, 8 Dec 2023 12:23:38 -0600 Subject: [PATCH 1/3] 2stackz: make with_frame preserve result and add preserve instances for Result and errors --- rust/ares/src/interpreter.rs | 37 ++++++++++++++++++++++++++++++++++++ rust/ares/src/jets.rs | 22 ++++++++++++++++++++- rust/ares/src/mem.rs | 29 +++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/rust/ares/src/interpreter.rs b/rust/ares/src/interpreter.rs index 2ebb7523..033c26c7 100644 --- a/rust/ares/src/interpreter.rs +++ b/rust/ares/src/interpreter.rs @@ -22,6 +22,7 @@ use std::result; use std::sync::atomic::Ordering; use std::sync::Arc; use std::time::Instant; +use crate::mem::Preserve; crate::gdb!(); @@ -292,6 +293,42 @@ pub enum Error { NonDeterministic(Noun), // trace } +impl Preserve for Error { + unsafe fn preserve(&mut self, stack: &mut NockStack) { + match self { + Error::ScryBlocked(ref mut path) => { + path.preserve(stack) + }, + Error::ScryCrashed(ref mut trace) => { + trace.preserve(stack) + }, + Error::Deterministic(ref mut trace) => { + trace.preserve(stack) + } + Error::NonDeterministic(ref mut trace) => { + trace.preserve(stack) + } + } + } + + unsafe fn assert_in_stack(&self, stack: &NockStack) { + match self { + Error::ScryBlocked(ref path) => { + path.assert_in_stack(stack) + }, + Error::ScryCrashed(ref trace) => { + trace.assert_in_stack(stack) + }, + Error::Deterministic(ref trace) => { + trace.assert_in_stack(stack) + } + Error::NonDeterministic(ref trace) => { + trace.assert_in_stack(stack) + } + } + } +} + impl From for Error { fn from(_: noun::Error) -> Self { Error::Deterministic(D(0)) diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs index 9f3b4b27..422ca479 100644 --- a/rust/ares/src/jets.rs +++ b/rust/ares/src/jets.rs @@ -34,7 +34,7 @@ use crate::jets::sort::*; use crate::jets::tree::*; use crate::jets::warm::Warm; -use crate::mem::NockStack; +use crate::mem::{NockStack, Preserve}; use crate::newt::Newt; use crate::noun::{self, Noun, Slots, D}; use ares_macros::tas; @@ -55,6 +55,26 @@ pub enum JetErr { Fail(Error), // Error; do not retry } +impl Preserve for JetErr { + unsafe fn preserve(&mut self, stack: &mut NockStack) { + match self { + JetErr::Punt => {}, + JetErr::Fail(ref mut err) => { + err.preserve(stack) + }, + } + } + + unsafe fn assert_in_stack(&self, stack: &NockStack) { + match self { + JetErr::Punt => {}, + JetErr::Fail(ref err) => { + err.assert_in_stack(stack) + }, + } + } +} + impl From for JetErr { fn from(err: Error) -> Self { Self::Fail(err) diff --git a/rust/ares/src/mem.rs b/rust/ares/src/mem.rs index f53b63b3..3a395472 100644 --- a/rust/ares/src/mem.rs +++ b/rust/ares/src/mem.rs @@ -664,9 +664,11 @@ impl NockStack { pub unsafe fn with_frame(&mut self, num_locals: usize, f: F) -> O where F: FnOnce() -> O, + O: Preserve { self.frame_push(num_locals); - let ret = f(); + let mut ret = f(); + ret.preserve(self); self.frame_pop(); ret } @@ -1133,3 +1135,28 @@ impl Stack for NockStack { self.layout_alloc(layout) } } + +impl Preserve for Result { + unsafe fn preserve(&mut self, stack: &mut NockStack) { + match self.as_mut() { + Ok(t_ref) => { + t_ref.preserve(stack) + }, + Err(e_ref) => { + e_ref.preserve(stack) + } + } + } + + unsafe fn assert_in_stack(&self, stack: &NockStack) { + match self.as_ref() { + Ok(t_ref) => { + t_ref.assert_in_stack(stack) + }, + Err(e_ref) => { + e_ref.assert_in_stack(stack) + } + } + } +} + From 529d8786cdda84c460be7fdc6c7fb1df30923591 Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Fri, 8 Dec 2023 12:28:04 -0600 Subject: [PATCH 2/3] stack: pass stack to with_frame closure --- rust/ares/src/mem.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ares/src/mem.rs b/rust/ares/src/mem.rs index 3a395472..40e73fd6 100644 --- a/rust/ares/src/mem.rs +++ b/rust/ares/src/mem.rs @@ -663,11 +663,11 @@ impl NockStack { */ pub unsafe fn with_frame(&mut self, num_locals: usize, f: F) -> O where - F: FnOnce() -> O, + F: FnOnce(&mut NockStack) -> O, O: Preserve { self.frame_push(num_locals); - let mut ret = f(); + let mut ret = f(self); ret.preserve(self); self.frame_pop(); ret From d7236aed41c1c29383bec32f0e9721f7d81264a4 Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Fri, 8 Dec 2023 12:44:55 -0600 Subject: [PATCH 3/3] interpreter: add with_stack_frame method to context --- rust/ares/src/interpreter.rs | 54 +++++++++++++++++++----------------- rust/ares/src/jets.rs | 12 +++----- rust/ares/src/mem.rs | 19 ++++--------- 3 files changed, 38 insertions(+), 47 deletions(-) diff --git a/rust/ares/src/interpreter.rs b/rust/ares/src/interpreter.rs index 033c26c7..94256993 100644 --- a/rust/ares/src/interpreter.rs +++ b/rust/ares/src/interpreter.rs @@ -9,6 +9,7 @@ use crate::jets::warm::Warm; use crate::jets::JetErr; use crate::mem::unifying_equality; use crate::mem::NockStack; +use crate::mem::Preserve; use crate::newt::Newt; use crate::noun; use crate::noun::{Atom, Cell, IndirectAtom, Noun, Slots, D, T}; @@ -22,7 +23,6 @@ use std::result; use std::sync::atomic::Ordering; use std::sync::Arc; use std::time::Instant; -use crate::mem::Preserve; crate::gdb!(); @@ -283,6 +283,26 @@ impl Context { self.cold = saved.cold; self.warm = saved.warm; } + + /** + * For jets that need a stack frame internally. + * + * This ensures that the frame is cleaned up even if the closure short-circuites to an error + * result using e.g. the ? syntax. We need this method separately from with_frame to allow the + * jet to use the entire context without the borrow checker complaining about the mutable + * references. + */ + pub unsafe fn with_stack_frame(&mut self, slots: usize, f: F) -> O + where + F: FnOnce(&mut Context) -> O, + O: Preserve, + { + self.stack.frame_push(slots); + let mut ret = f(self); + ret.preserve(&mut self.stack); + self.stack.frame_pop(); + ret + } } #[derive(Clone, Copy, Debug)] @@ -296,35 +316,19 @@ pub enum Error { impl Preserve for Error { unsafe fn preserve(&mut self, stack: &mut NockStack) { match self { - Error::ScryBlocked(ref mut path) => { - path.preserve(stack) - }, - Error::ScryCrashed(ref mut trace) => { - trace.preserve(stack) - }, - Error::Deterministic(ref mut trace) => { - trace.preserve(stack) - } - Error::NonDeterministic(ref mut trace) => { - trace.preserve(stack) - } + Error::ScryBlocked(ref mut path) => path.preserve(stack), + Error::ScryCrashed(ref mut trace) => trace.preserve(stack), + Error::Deterministic(ref mut trace) => trace.preserve(stack), + Error::NonDeterministic(ref mut trace) => trace.preserve(stack), } } unsafe fn assert_in_stack(&self, stack: &NockStack) { match self { - Error::ScryBlocked(ref path) => { - path.assert_in_stack(stack) - }, - Error::ScryCrashed(ref trace) => { - trace.assert_in_stack(stack) - }, - Error::Deterministic(ref trace) => { - trace.assert_in_stack(stack) - } - Error::NonDeterministic(ref trace) => { - trace.assert_in_stack(stack) - } + Error::ScryBlocked(ref path) => path.assert_in_stack(stack), + Error::ScryCrashed(ref trace) => trace.assert_in_stack(stack), + Error::Deterministic(ref trace) => trace.assert_in_stack(stack), + Error::NonDeterministic(ref trace) => trace.assert_in_stack(stack), } } } diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs index 422ca479..5bff6b13 100644 --- a/rust/ares/src/jets.rs +++ b/rust/ares/src/jets.rs @@ -58,19 +58,15 @@ pub enum JetErr { impl Preserve for JetErr { unsafe fn preserve(&mut self, stack: &mut NockStack) { match self { - JetErr::Punt => {}, - JetErr::Fail(ref mut err) => { - err.preserve(stack) - }, + JetErr::Punt => {} + JetErr::Fail(ref mut err) => err.preserve(stack), } } unsafe fn assert_in_stack(&self, stack: &NockStack) { match self { - JetErr::Punt => {}, - JetErr::Fail(ref err) => { - err.assert_in_stack(stack) - }, + JetErr::Punt => {} + JetErr::Fail(ref err) => err.assert_in_stack(stack), } } } diff --git a/rust/ares/src/mem.rs b/rust/ares/src/mem.rs index 40e73fd6..9ba1997f 100644 --- a/rust/ares/src/mem.rs +++ b/rust/ares/src/mem.rs @@ -664,7 +664,7 @@ impl NockStack { pub unsafe fn with_frame(&mut self, num_locals: usize, f: F) -> O where F: FnOnce(&mut NockStack) -> O, - O: Preserve + O: Preserve, { self.frame_push(num_locals); let mut ret = f(self); @@ -1139,24 +1139,15 @@ impl Stack for NockStack { impl Preserve for Result { unsafe fn preserve(&mut self, stack: &mut NockStack) { match self.as_mut() { - Ok(t_ref) => { - t_ref.preserve(stack) - }, - Err(e_ref) => { - e_ref.preserve(stack) - } + Ok(t_ref) => t_ref.preserve(stack), + Err(e_ref) => e_ref.preserve(stack), } } unsafe fn assert_in_stack(&self, stack: &NockStack) { match self.as_ref() { - Ok(t_ref) => { - t_ref.assert_in_stack(stack) - }, - Err(e_ref) => { - e_ref.assert_in_stack(stack) - } + Ok(t_ref) => t_ref.assert_in_stack(stack), + Err(e_ref) => e_ref.assert_in_stack(stack), } } } -