Skip to content

Commit

Permalink
rune: Store Format in AnyObj instead of Mutable (relates #844)
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Oct 28, 2024
1 parent ca2687e commit 4bc845a
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 57 deletions.
2 changes: 1 addition & 1 deletion crates/rune/src/compile/v1/assemble.rs
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ fn block_without_scope<'a, 'hir>(
Ok(Asm::new(hir, ()))
}

/// Assemble #[builtin] format_args!(...) macro.
/// Assemble #[builtin] format!(...) macro.
#[instrument_ast(span = format)]
fn builtin_format<'a, 'hir>(
cx: &mut Ctxt<'a, 'hir, '_>,
Expand Down
4 changes: 1 addition & 3 deletions crates/rune/src/exported_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@ macro_rules! vm_write {
($($tt:tt)*) => {
match core::write!($($tt)*) {
Ok(()) => $crate::runtime::VmResult::Ok(()),
Err(err) => {
return $crate::runtime::VmResult::Err($crate::runtime::VmError::from(err));
}
Err(err) => $crate::runtime::VmResult::Err($crate::runtime::VmError::from(err)),
}
};
}
Expand Down
70 changes: 61 additions & 9 deletions crates/rune/src/modules/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use core::fmt;

use crate as rune;
use crate::alloc::fmt::TryWrite;
use crate::alloc::prelude::*;
use crate::compile;
use crate::macros::{FormatArgs, MacroContext, TokenStream};
use crate::parse::Parser;
use crate::runtime::{Format, Formatter, VmResult};
use crate::runtime::{EnvProtocolCaller, Format, Formatter, VmResult};
use crate::{ContextError, Module};

/// Formatting text.
Expand All @@ -23,14 +24,20 @@ use crate::{ContextError, Module};
/// ```
#[rune::module(::std::fmt)]
pub fn module() -> Result<Module, ContextError> {
let mut module = Module::from_meta(self::module_meta)?.with_unique("std::fmt");

module.ty::<Format>()?;
module.ty::<Formatter>()?;
module.ty::<fmt::Error>()?;
module.function_meta(fmt_error_string_display)?;
module.macro_meta(format)?;
Ok(module)
let mut m = Module::from_meta(self::module_meta)?.with_unique("std::fmt");

m.ty::<Formatter>()?;
m.ty::<fmt::Error>()?;
m.function_meta(fmt_error_string_display)?;
m.macro_meta(format)?;

m.ty::<Format>()?;
m.function_meta(format_string_display__meta)?;
m.function_meta(format_string_debug__meta)?;
m.function_meta(format_clone__meta)?;
m.implement_trait::<Format>(rune::item!(::std::clone::Clone))?;

Ok(m)
}

#[rune::function(instance, protocol = STRING_DISPLAY)]
Expand Down Expand Up @@ -58,3 +65,48 @@ pub(crate) fn format(
let expanded = args.expand(cx)?;
Ok(expanded.into_token_stream(cx)?)
}

/// Write a display representation of a format specification.
///
/// # Examples
///
/// ```rune
/// let value = #[builtin] format!("Hello", fill = '0', width = 10);
/// assert_eq!(format!("{value}"), "Hello00000");
/// ```
#[rune::function(keep, instance, protocol = STRING_DISPLAY)]
fn format_string_display(format: &Format, f: &mut Formatter) -> VmResult<()> {
VmResult::Ok(vm_try!(format.spec.format(
&format.value,
f,
&mut EnvProtocolCaller
)))
}

/// Write a debug representation of a format specification.
///
/// # Examples
///
/// ```rune
/// let value = #[builtin] format!("Hello", fill = '0', width = 10);
/// let string = format!("{value:?}");
/// assert!(string is String);
/// ```
#[rune::function(keep, instance, protocol = STRING_DEBUG)]
fn format_string_debug(format: &Format, f: &mut Formatter) -> VmResult<()> {
VmResult::Ok(vm_try!(vm_write!(f, "{format:?}")))
}

/// Clones a format specification.
///
/// # Examples
///
/// ```rune
/// let value = #[builtin] format!("Hello", fill = '0', width = 10);
/// let vlaue2 = value.clone();
/// assert_eq!(format!("{value}"), "Hello00000");
/// ```
#[rune::function(keep, instance, protocol = CLONE)]
fn format_clone(this: &Format) -> VmResult<Format> {
VmResult::Ok(vm_try!(this.try_clone()))
}
5 changes: 2 additions & 3 deletions crates/rune/src/runtime/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,15 @@ impl fmt::Display for AlignmentFromStrError {

/// A format specification, wrapping an inner value.
#[derive(Any, Debug, Clone, TryClone)]
#[rune(builtin, static_type = FORMAT)]
#[rune(static_type = FORMAT)]
pub struct Format {
/// The value being formatted.
pub(crate) value: Value,
/// The specification.
#[try_clone(copy)]
pub(crate) spec: FormatSpec,
}

from_value2!(Format, into_format_ref, into_format_mut, into_format);

/// A format specification.
#[derive(Debug, Clone, Copy, TryClone, Serialize, Deserialize, Decode, Encode)]
#[try_clone(copy)]
Expand Down
1 change: 1 addition & 0 deletions crates/rune/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ mod vec_tuple;
pub use self::vec_tuple::VecTuple;

mod vm;
use self::vm::CallResultOnly;
pub use self::vm::{CallFrame, Isolated, Vm};

mod vm_call;
Expand Down
48 changes: 11 additions & 37 deletions crates/rune/src/runtime/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ use crate::alloc::fmt::TryWrite;
use crate::alloc::prelude::*;
use crate::alloc::{self, String};
use crate::compile::meta;
use crate::runtime::static_type;
use crate::runtime::vm::CallResultOnly;
use crate::runtime::{
AccessError, AnyObj, AnyObjDrop, BorrowMut, BorrowRef, Bytes, ConstValue, ControlFlow,
DynGuardedArgs, EnvProtocolCaller, Format, Formatter, FromValue, Function, Future, Generator,
GeneratorState, IntoOutput, Iterator, MaybeTypeOf, Mut, Object, OwnedTuple, Protocol,
ProtocolCaller, RawAnyObjGuard, Ref, RuntimeError, Shared, Snapshot, Stream, ToValue, Type,
TypeInfo, Variant, Vec, Vm, VmErrorKind, VmIntegerRepr, VmResult,
use crate::{Any, Hash};

use super::static_type;
use super::{
AccessError, AnyObj, AnyObjDrop, BorrowMut, BorrowRef, Bytes, CallResultOnly, ConstValue,
ControlFlow, DynGuardedArgs, EnvProtocolCaller, Format, Formatter, FromValue, Function, Future,
Generator, GeneratorState, IntoOutput, Iterator, MaybeTypeOf, Mut, Object, OwnedTuple,
Protocol, ProtocolCaller, RawAnyObjGuard, Ref, RuntimeError, Shared, Snapshot, Stream, ToValue,
Type, TypeInfo, Variant, Vec, Vm, VmErrorKind, VmIntegerRepr, VmResult,
};
#[cfg(feature = "alloc")]
use crate::runtime::{Hasher, Tuple};
use crate::{Any, Hash};
use super::{Hasher, Tuple};

/// Defined guard for a reference value.
///
Expand Down Expand Up @@ -370,14 +370,6 @@ impl Value {
break 'fallback;
}
},
BorrowRefRepr::Mutable(value) => match &*value {
Mutable::Format(format) => {
vm_try!(format.spec.format(&format.value, f, caller));
}
_ => {
break 'fallback;
}
},
_ => {
break 'fallback;
}
Expand Down Expand Up @@ -435,7 +427,6 @@ impl Value {
Mutable::Struct(value) => Mutable::Struct(vm_try!(value.try_clone())),
Mutable::Variant(value) => Mutable::Variant(vm_try!(value.try_clone())),
Mutable::Function(value) => Mutable::Function(vm_try!(value.try_clone())),
Mutable::Format(value) => Mutable::Format(vm_try!(value.try_clone())),
_ => {
break 'fallback;
}
Expand Down Expand Up @@ -537,9 +528,6 @@ impl Value {
Mutable::Function(value) => {
vm_try!(vm_write!(f, "{value:?}"));
}
Mutable::Format(value) => {
vm_try!(vm_write!(f, "{value:?}"));
}
};

return VmResult::Ok(());
Expand Down Expand Up @@ -873,16 +861,6 @@ impl Value {
into_generator,
}

into! {
/// Coerce into a [`Format`].
Format(Format),
into_format_ref,
into_format_mut,
borrow_format_ref,
borrow_format_mut,
into_format,
}

into! {
/// Coerce into [`Tuple`].
Tuple(OwnedTuple),
Expand Down Expand Up @@ -1973,14 +1951,14 @@ from! {
Object => Object,
Tuple => OwnedTuple,
Generator => Generator<Vm>,
Format => Format,
Future => Future,
Stream => Stream<Vm>,
}

any_from! {
String,
Bytes,
Format,
}

from_container! {
Expand Down Expand Up @@ -2283,8 +2261,6 @@ pub(crate) enum Mutable {
Variant(Variant),
/// A stored function pointer.
Function(Function),
/// A value being formatted.
Format(Format),
}

impl Mutable {
Expand All @@ -2301,7 +2277,6 @@ impl Mutable {
Mutable::Option(..) => TypeInfo::static_type(static_type::OPTION),
Mutable::Result(..) => TypeInfo::static_type(static_type::RESULT),
Mutable::Function(..) => TypeInfo::static_type(static_type::FUNCTION),
Mutable::Format(..) => TypeInfo::static_type(static_type::FORMAT),
Mutable::EmptyStruct(empty) => empty.type_info(),
Mutable::TupleStruct(tuple) => tuple.type_info(),
Mutable::Struct(object) => object.type_info(),
Expand All @@ -2326,7 +2301,6 @@ impl Mutable {
Mutable::Result(..) => static_type::RESULT.hash,
Mutable::Option(..) => static_type::OPTION.hash,
Mutable::Function(..) => static_type::FUNCTION.hash,
Mutable::Format(..) => static_type::FORMAT.hash,
Mutable::EmptyStruct(empty) => empty.rtti.hash,
Mutable::TupleStruct(tuple) => tuple.rtti.hash,
Mutable::Struct(object) => object.rtti.hash,
Expand Down
3 changes: 0 additions & 3 deletions crates/rune/src/runtime/value/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ impl ser::Serialize for Value {
Mutable::Function(..) => {
Err(ser::Error::custom("cannot serialize function pointers"))
}
Mutable::Format(..) => {
Err(ser::Error::custom("cannot serialize format specifications"))
}
Mutable::ControlFlow(..) => {
Err(ser::Error::custom("cannot serialize `start..end` ranges"))
}
Expand Down
2 changes: 1 addition & 1 deletion crates/rune/src/runtime/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2966,7 +2966,7 @@ impl Vm {
#[cfg_attr(feature = "bench", inline(never))]
fn op_format(&mut self, addr: InstAddress, spec: FormatSpec, out: Output) -> VmResult<()> {
let value = vm_try!(self.stack.at(addr)).clone();
vm_try!(out.store(&mut self.stack, Mutable::Format(Format { value, spec })));
vm_try!(out.store(&mut self.stack, || Format { value, spec }));
VmResult::Ok(())
}

Expand Down

0 comments on commit 4bc845a

Please sign in to comment.