diff --git a/src/bytecode.rs b/src/bytecode.rs index c2075f01..afa7ffff 100755 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -868,8 +868,8 @@ fn byte_code<'ob>( ) -> Result> { let fun = crate::alloc::make_byte_code( 0, - bytestr.get(cx), - vector.get(cx), + bytestr.untag(cx), + vector.untag(cx), maxdepth, None, None, diff --git a/src/core/gc/root.rs b/src/core/gc/root.rs index b6615e8a..d9d968ee 100644 --- a/src/core/gc/root.rs +++ b/src/core/gc/root.rs @@ -370,7 +370,8 @@ impl Rt> { } } - pub(crate) fn get<'ob, U>(&self, cx: &'ob Context) -> U + /// Calls [untag](Untag::untag_erased) on the tagged Gc pointer + pub(crate) fn untag<'ob, U>(&self, cx: &'ob Context) -> U where Gc: WithLifetime<'ob, Out = Gc> + Copy, Gc: Untag, diff --git a/src/core/object/tagged.rs b/src/core/object/tagged.rs index 79400053..82365c1c 100755 --- a/src/core/object/tagged.rs +++ b/src/core/object/tagged.rs @@ -113,13 +113,9 @@ impl Gc { } } -impl Gc { - pub(crate) fn untag(self) -> T { - T::untag(self) - } -} - -/// Untag a type erased `Gc` value. This is useful in generic code. +/// The [TaggedPtr] trait is local to this module (by design). This trait +/// exports the one pubic method we want (untag) so it can be used in other +/// modules. pub(crate) trait Untag { fn untag_erased(self) -> T; } @@ -130,6 +126,18 @@ impl Untag for Gc { } } +impl Gc +where + Gc: Untag, +{ + /// A non-trait version of [Untag::untag_erased]. This is useful when we + /// don't want to import the trait all over the place. The only time we need + /// to import the trait is in generic code. + pub(crate) fn untag(self) -> T { + Self::untag_erased(self) + } +} + /// A wrapper trait to expose the `tag` method for GC managed references and /// immediate values. This is convenient when we don't have access to the /// `Context` but want to retag a value. Doesn't currently have a lot of use. @@ -392,7 +400,7 @@ mod private { /// /// Every method has a default implementation, and the doc string /// indicates if it should be reimplemented or left untouched. - pub(crate) trait TaggedPtr: Copy + for<'a> WithLifetime<'a> { + pub(super) trait TaggedPtr: Copy + for<'a> WithLifetime<'a> { /// The type of object being pointed to. This will be different for all /// implementors. type Ptr; diff --git a/src/eval.rs b/src/eval.rs index d95ae9fb..afef46ab 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -206,7 +206,7 @@ fn run_hook_with_args<'ob>( env: &mut Rt, cx: &'ob mut Context, ) -> Result> { - match hook.get(cx) { + match hook.untag(cx) { Object::Symbol(sym) => { if let Some(val) = env.vars.get(sym) { let val = val.bind(cx); @@ -244,7 +244,7 @@ pub(crate) fn autoload_do_load<'ob>( cx: &'ob mut Context, ) -> Result> { // TODO: want to handle the case where the file is already loaded. - match fundef.get(cx) { + match fundef.untag(cx) { Object::Cons(cons) if cons.car() == sym::AUTOLOAD => { ensure!(macro_only.is_none(), "autoload-do-load macro-only is not yet implemented"); let mut iter = cons.elements(); @@ -260,7 +260,7 @@ pub(crate) fn autoload_do_load<'ob>( root!(file, cx); crate::lread::load(file, None, None, cx, env)?; match funname { - Some(func) => match func.get(cx).func(cx) { + Some(func) => match func.untag(cx).func(cx) { Some(x) => Ok(x.into()), None => Err(anyhow!("autoload of {func} did not provide a definition")), }, @@ -295,7 +295,7 @@ pub(crate) fn macroexpand<'ob>( cx: &'ob mut Context, env: &mut Rt, ) -> Result> { - let Object::Cons(cons) = form.get(cx) else { return Ok(form.bind(cx)) }; + let Object::Cons(cons) = form.untag(cx) else { return Ok(form.bind(cx)) }; let Object::Symbol(sym) = cons.car().untag() else { return Ok(form.bind(cx)) }; // shadow the macro based on ENVIRONMENT let func = match environment { @@ -428,7 +428,7 @@ impl Rt>> { let name = name.unwrap_or("lambda"); let arg_cnt = frame.arg_count(); debug!("calling {self:?}"); - match self.get(cx) { + match self.untag(cx) { Function::ByteFn(f) => { root!(f, cx); frame.set_depth(f.bind(cx).depth); diff --git a/src/fileio.rs b/src/fileio.rs index 155fedf3..4d97b38c 100644 --- a/src/fileio.rs +++ b/src/fileio.rs @@ -27,7 +27,7 @@ pub(crate) fn expand_file_name( Ok(path.join(name).to_string_lossy().to_string()) } else { let dir = env.vars.get(sym::DEFAULT_DIRECTORY).unwrap(); - match dir.get(cx) { + match dir.untag(cx) { Object::String(s) => { let name: &str = s.try_into()?; let path = Path::new(name); diff --git a/src/fns.rs b/src/fns.rs index bed6cd1c..209db13e 100644 --- a/src/fns.rs +++ b/src/fns.rs @@ -151,7 +151,7 @@ pub(crate) fn mapc<'ob>( env: &mut Rt, cx: &'ob mut Context, ) -> Result> { - match sequence.get(cx) { + match sequence.untag(cx) { List::Nil => Ok(NIL), List::Cons(cons) => { rooted_iter!(elements, cons, cx); @@ -492,18 +492,18 @@ pub(crate) fn require<'ob>( cx: &'ob mut Context, ) -> Result> { // TODO: Fix this unsafe into_root - let feat = unsafe { feature.get(cx).into_root() }; + let feat = unsafe { feature.untag(cx).into_root() }; if crate::data::features().lock().unwrap().contains(&feat) { - return Ok(feature.get(cx)); + return Ok(feature.untag(cx)); } let file = match filename { - Some(file) => file.get(cx).try_into()?, - None => feature.get(cx).get().name(), + Some(file) => file.untag(cx).try_into()?, + None => feature.untag(cx).get().name(), }; let file = file.into_obj(cx); root!(file, cx); match crate::lread::load(file, None, None, cx, env) { - Ok(_) => Ok(feature.get(cx)), + Ok(_) => Ok(feature.untag(cx)), Err(e) => match noerror { Some(()) => Ok(sym::NIL), None => Err(e), diff --git a/src/interpreter.rs b/src/interpreter.rs index 891f689c..4bacaec8 100755 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -37,7 +37,7 @@ pub(crate) fn eval<'ob>( impl Interpreter<'_, '_> { fn eval_form<'ob>(&mut self, rt: &Rt, cx: &'ob mut Context) -> EvalResult<'ob> { - match rt.get(cx) { + match rt.untag(cx) { Object::Symbol(sym) => self.var_ref(sym, cx), Object::Cons(_) => { let x = rt.try_into().unwrap(); @@ -155,7 +155,7 @@ impl Interpreter<'_, '_> { }; root!(func, cx); - match func.get(cx) { + match func.untag(cx) { Function::Cons(cons) if cons.car() == sym::AUTOLOAD => { crate::eval::autoload_do_load(func.use_as(), None, None, self.env, cx) .map_err(|e| add_trace(e, "autoload", &[]))?; @@ -453,13 +453,13 @@ impl Interpreter<'_, '_> { let mut varbind_count = 0; rooted_iter!(bindings, form, cx); while let Some(binding) = bindings.next()? { - match binding.get(cx) { + match binding.untag(cx) { // (let ((x y))) Object::Cons(_) => { let cons = binding.as_cons(); let val = rebind!(self.let_bind_value(cons, cx)?); let var: Symbol = - cons.get(cx).car().try_into().context("let variable must be a symbol")?; + cons.untag(cx).car().try_into().context("let variable must be a symbol")?; varbind_count += self.create_let_binding(var, val, cx); } // (let (x)) @@ -477,13 +477,13 @@ impl Interpreter<'_, '_> { root!(let_bindings, Vec::new(), cx); rooted_iter!(bindings, form, cx); while let Some(binding) = bindings.next()? { - match binding.get(cx) { + match binding.untag(cx) { // (let ((x y))) Object::Cons(_) => { let cons = binding.as_cons(); let var = rebind!(self.let_bind_value(cons, cx)?); let sym: Symbol = - cons.get(cx).car().try_into().context("let variable must be a symbol")?; + cons.untag(cx).car().try_into().context("let variable must be a symbol")?; let_bindings.push((sym, var)); } // (let (x)) @@ -602,7 +602,7 @@ impl Interpreter<'_, '_> { return Err(err); } while let Some(handler) = forms.next()? { - match handler.get(cx) { + match handler.untag(cx) { Object::Cons(cons) => { // Check that conditions match let condition = cons.car(); @@ -657,7 +657,7 @@ pub(crate) fn call_closure<'ob>( cx: &'ob mut Context, ) -> EvalResult<'ob> { cx.garbage_collect(false); - let closure: &Cons = closure.get(cx); + let closure: &Cons = closure.untag(cx); match closure.car().untag() { Object::Symbol(sym::CLOSURE) => { rooted_iter!(forms, closure.cdr(), cx); diff --git a/src/lread.rs b/src/lread.rs index b1474cee..a6ad2359 100644 --- a/src/lread.rs +++ b/src/lread.rs @@ -120,7 +120,7 @@ pub(crate) fn load( ) -> Result { let noerror = noerror.is_some(); let nomessage = nomessage.is_some(); - let file: &str = file.get(cx).try_into()?; + let file: &str = file.untag(cx).try_into()?; let final_file = if Path::new(file).exists() { PathBuf::from(file) } else {