Skip to content

Commit

Permalink
rune: Implement and use Dynamic container
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Nov 3, 2024
1 parent de5f636 commit 6cbd6be
Show file tree
Hide file tree
Showing 32 changed files with 896 additions and 1,413 deletions.
4 changes: 2 additions & 2 deletions crates/rune-macros/src/from_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl Expander<'_> {
#[automatically_derived]
impl #from_value for #ident {
fn from_value(value: #value) -> #result<Self, #runtime_error> {
match #value::into_type_value(value)? {
match #value::as_type_value(&value)? {
#expanded
actual => {
#result::Err(#runtime_error::expected::<#expected>(#type_value::type_info(&actual)))
Expand Down Expand Up @@ -177,7 +177,7 @@ impl Expander<'_> {
#[automatically_derived]
impl #from_value for #ident {
fn from_value(value: #value) -> #result<Self, #runtime_error> {
match #value::into_type_value(value)? {
match #value::as_type_value(&value)? {
#variant,
actual => {
#result::Err(#runtime_error::__rune_macros__expected_variant(#type_value::type_info(&actual)))
Expand Down
9 changes: 8 additions & 1 deletion crates/rune/src/compile/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::module::{
};
use crate::runtime::{
AnyTypeInfo, ConstConstruct, ConstContext, ConstValue, FunctionHandler, InstAddress, Memory,
Output, Protocol, Rtti, RuntimeContext, TypeCheck, TypeInfo, VmResult,
Output, Protocol, Rtti, RttiKind, RuntimeContext, TypeCheck, TypeInfo, VmResult,
};
use crate::{Hash, Item, ItemBuf};

Expand Down Expand Up @@ -764,6 +764,12 @@ impl Context {
continue;
};

let kind = match fields {
Fields::Empty => RttiKind::Empty,
Fields::Unnamed(..) => RttiKind::Tuple,
Fields::Named(..) => RttiKind::Struct,
};

let item = ty.item.extended(variant.name)?;
let hash = Hash::type_hash(&item);

Expand All @@ -772,6 +778,7 @@ impl Context {
hash,
type_check: None,
type_info: TypeInfo::rtti(Arc::new(Rtti {
kind,
hash: ty.hash,
variant_hash: hash,
item: item.try_clone()?,
Expand Down
2 changes: 1 addition & 1 deletion crates/rune/src/compile/ir/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ fn eval_ir_template(
return Err(EvalOutcome::not_const(ir));
}
},
ReprRef::Mutable(..) => {
ReprRef::Dynamic(..) => {
return Err(EvalOutcome::not_const(ir));
}
}
Expand Down
24 changes: 9 additions & 15 deletions crates/rune/src/compile/ir/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,10 @@ impl ir::Scopes {
value.type_info(),
));
}
ReprRef::Mutable(value) => {
ReprRef::Dynamic(value) => {
return Err(compile::Error::expected_type::<OwnedTuple>(
ir_target,
value.borrow_ref().with_span(ir_target)?.type_info(),
value.type_info(),
));
}
ReprRef::Any(value) => match value.type_hash() {
Expand Down Expand Up @@ -277,12 +277,10 @@ impl ir::Scopes {
value.type_info(),
));
}
ReprRef::Mutable(current) => {
let mutable = current.borrow_mut().with_span(ir_target)?;

ReprRef::Dynamic(value) => {
return Err(compile::Error::expected_type::<OwnedTuple>(
ir_target,
mutable.type_info(),
value.type_info(),
));
}
ReprRef::Any(any) => match any.type_hash() {
Expand Down Expand Up @@ -348,14 +346,10 @@ impl ir::Scopes {
let current = self.get_target(target)?;

match current.as_ref().with_span(ir_target)? {
ReprRef::Mutable(value) => {
let value = value.borrow_ref().with_span(ir_target)?;

Err(compile::Error::expected_type::<OwnedTuple>(
ir_target,
value.type_info(),
))
}
ReprRef::Dynamic(value) => Err(compile::Error::expected_type::<OwnedTuple>(
ir_target,
value.type_info(),
)),
ReprRef::Any(value) => match value.type_hash() {
runtime::Vec::HASH => {
let mut vec =
Expand Down Expand Up @@ -391,7 +385,7 @@ impl ir::Scopes {
},
actual => Err(compile::Error::expected_type::<OwnedTuple>(
ir_target,
actual.type_info().with_span(ir_target)?,
actual.type_info(),
)),
}
}
Expand Down
10 changes: 9 additions & 1 deletion crates/rune/src/compile/unit_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use crate::query::QueryInner;
use crate::runtime::debug::{DebugArgs, DebugSignature};
use crate::runtime::unit::UnitEncoder;
use crate::runtime::{
Call, ConstValue, DebugInfo, DebugInst, Inst, Label, Protocol, Rtti, StaticString, Unit, UnitFn,
Call, ConstValue, DebugInfo, DebugInst, Inst, Label, Protocol, Rtti, RttiKind, StaticString,
Unit, UnitFn,
};
use crate::{Context, Diagnostics, Hash, Item, SourceId};

Expand Down Expand Up @@ -312,6 +313,7 @@ impl UnitBuilder {
let hash = pool.item_type_hash(meta.item_meta.item);

let rtti = Arc::new(Rtti {
kind: RttiKind::Empty,
hash,
variant_hash: Hash::EMPTY,
item: pool.item(meta.item_meta.item).try_to_owned()?,
Expand Down Expand Up @@ -344,6 +346,7 @@ impl UnitBuilder {
);

let rtti = Arc::new(Rtti {
kind: RttiKind::Empty,
hash: meta.hash,
variant_hash: Hash::EMPTY,
item: pool.item(meta.item_meta.item).try_to_owned()?,
Expand Down Expand Up @@ -402,6 +405,7 @@ impl UnitBuilder {
);

let rtti = Arc::new(Rtti {
kind: RttiKind::Tuple,
hash: meta.hash,
variant_hash: Hash::EMPTY,
item: pool.item(meta.item_meta.item).try_to_owned()?,
Expand Down Expand Up @@ -452,6 +456,7 @@ impl UnitBuilder {
let hash = pool.item_type_hash(meta.item_meta.item);

let rtti = Arc::new(Rtti {
kind: RttiKind::Struct,
hash,
variant_hash: Hash::EMPTY,
item: pool.item(meta.item_meta.item).try_to_owned()?,
Expand All @@ -478,6 +483,7 @@ impl UnitBuilder {
..
} => {
let rtti = Arc::new(Rtti {
kind: RttiKind::Empty,
hash: enum_hash,
variant_hash: meta.hash,
item: pool.item(meta.item_meta.item).try_to_owned()?,
Expand Down Expand Up @@ -527,6 +533,7 @@ impl UnitBuilder {
..
} => {
let rtti = Arc::new(Rtti {
kind: RttiKind::Tuple,
hash: enum_hash,
variant_hash: meta.hash,
item: pool.item(meta.item_meta.item).try_to_owned()?,
Expand Down Expand Up @@ -581,6 +588,7 @@ impl UnitBuilder {
let hash = pool.item_type_hash(meta.item_meta.item);

let rtti = Arc::new(Rtti {
kind: RttiKind::Struct,
hash: enum_hash,
variant_hash: hash,
item: pool.item(meta.item_meta.item).try_to_owned()?,
Expand Down
1 change: 0 additions & 1 deletion crates/rune/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,6 @@ impl_builtin_type_of! {

impl ::std::tuple::Tuple, crate::runtime::Tuple;

impl ::std::object::Object, crate::runtime::Struct;
impl<T> ::std::object::Object, crate::alloc::HashMap<::rust_alloc::string::String, T>;
impl<T> ::std::object::Object, crate::alloc::HashMap<alloc::String, T>;

Expand Down
8 changes: 4 additions & 4 deletions crates/rune/src/modules/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ where
VmErrorKind::bad_argument(index),
]);
}
ReprRef::Mutable(value) => {
ReprRef::Dynamic(value) => {
return VmResult::err([
VmErrorKind::expected::<Future>(vm_try!(value.borrow_ref()).type_info()),
VmErrorKind::expected::<Future>(value.type_info()),
VmErrorKind::bad_argument(index),
]);
}
Expand Down Expand Up @@ -106,9 +106,9 @@ async fn join(value: Value) -> VmResult<Value> {
VmErrorKind::expected::<runtime::Vec>(value.type_info()),
]),
},
ReprRef::Mutable(value) => VmResult::err([
ReprRef::Dynamic(value) => VmResult::err([
VmErrorKind::bad_argument(0),
VmErrorKind::expected::<runtime::Vec>(vm_try!(value.borrow_ref()).type_info()),
VmErrorKind::expected::<runtime::Vec>(value.type_info()),
]),
ReprRef::Any(value) => match value.type_hash() {
runtime::Vec::HASH => {
Expand Down
6 changes: 2 additions & 4 deletions crates/rune/src/modules/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,10 +480,8 @@ pub fn module() -> Result<Module, ContextError> {
ReprRef::Inline(value) => {
return VmResult::expected::<String>(value.type_info());
}
ReprRef::Mutable(value) => {
return VmResult::expected::<String>(
vm_try!(value.borrow_ref()).type_info(),
);
ReprRef::Dynamic(value) => {
return VmResult::expected::<String>(value.type_info());
}
ReprRef::Any(value) => match value.type_hash() {
String::HASH => {
Expand Down
8 changes: 4 additions & 4 deletions crates/rune/src/modules/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,8 +896,8 @@ fn split(this: Ref<str>, value: Value) -> VmResult<Value> {
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]),
ReprRef::Mutable(value) => VmResult::err([
VmErrorKind::expected::<String>(vm_try!(value.borrow_ref()).type_info()),
ReprRef::Dynamic(value) => VmResult::err([
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]),
ReprRef::Any(value) => match value.type_hash() {
Expand Down Expand Up @@ -945,9 +945,9 @@ fn split_once(this: &str, value: Value) -> VmResult<Option<(String, String)>> {
VmErrorKind::bad_argument(0),
]);
}
ReprRef::Mutable(value) => {
ReprRef::Dynamic(value) => {
return VmResult::err([
VmErrorKind::expected::<String>(vm_try!(value.borrow_ref()).type_info()),
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]);
}
Expand Down
4 changes: 2 additions & 2 deletions crates/rune/src/runtime/const_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ impl ConstValue {
pub(crate) fn from_value_ref(value: &Value) -> Result<ConstValue, RuntimeError> {
let inner = match value.as_ref()? {
ReprRef::Inline(value) => ConstValueKind::Inline(*value),
ReprRef::Mutable(value) => {
ReprRef::Dynamic(value) => {
return Err(RuntimeError::from(VmErrorKind::ConstNotSupported {
actual: value.borrow_ref()?.type_info(),
actual: value.type_info(),
}));
}
ReprRef::Any(value) => match value.type_hash() {
Expand Down
123 changes: 123 additions & 0 deletions crates/rune/src/runtime/dynamic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use core::borrow::Borrow;
use core::hash::Hash;
use core::ops::Deref;

use crate::alloc::{Box, Vec};

use super::{FromValue, ReprOwned, Rtti, RttiKind, RuntimeError, Tuple, TypeInfo, Value};

use rust_alloc::sync::Arc;

/// A reference to a dynamically defined empty type.
pub struct DynamicEmpty {
rtti: Arc<Rtti>,
}

impl FromValue for DynamicEmpty {
#[inline]
fn from_value(value: Value) -> Result<Self, RuntimeError> {
match value.take_repr()? {
ReprOwned::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Empty) => Ok(Self {
rtti: value.rtti().clone(),
}),
value => Err(RuntimeError::expected_empty(value.type_info())),
}
}
}

impl DynamicEmpty {
/// Get human readable type information for the dynamic tuple.
pub fn type_info(&self) -> TypeInfo {
self.rtti.clone().type_info()
}
}

/// A reference to a dynamically defined tuple.
///
/// This derefs into a [`Tuple`], which can be used to access the individual
/// fields.
pub struct DynamicTuple {
rtti: Arc<Rtti>,
values: Vec<Value>,
}

impl FromValue for DynamicTuple {
#[inline]
fn from_value(value: Value) -> Result<Self, RuntimeError> {
match value.take_repr()? {
ReprOwned::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Tuple) => {
let mut values = Vec::try_with_capacity(value.len())?;

for value in value.borrow_ref()?.iter() {
values.try_push(value.clone())?;
}

Ok(Self {
rtti: value.rtti().clone(),
values,
})
}
value => Err(RuntimeError::expected_tuple(value.type_info())),
}
}
}

impl DynamicTuple {
/// Get human readable type information for the dynamic tuple.
pub fn type_info(&self) -> TypeInfo {
self.rtti.clone().type_info()
}
}

impl Deref for DynamicTuple {
type Target = Tuple;

#[inline]
fn deref(&self) -> &Self::Target {
Tuple::new(&self.values)
}
}

/// A reference to a dynamically defined struct.
pub struct DynamicStruct {
rtti: Arc<Rtti>,
values: Vec<Value>,
}

impl FromValue for DynamicStruct {
#[inline]
fn from_value(value: Value) -> Result<Self, RuntimeError> {
match value.take_repr()? {
ReprOwned::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Struct) => {
let mut values = Vec::try_with_capacity(value.len())?;

for value in value.borrow_ref()?.iter() {
values.try_push(value.clone())?;
}

Ok(Self {
rtti: value.rtti().clone(),
values,
})
}
value => Err(RuntimeError::expected_struct(value.type_info())),
}
}
}

impl DynamicStruct {
/// Get a value from the dynamic struct.
pub fn get<Q>(&self, key: &Q) -> Option<&Value>
where
Box<str>: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
let index = *self.rtti.fields.get(key)?;
self.values.get(index)
}

/// Get human readable type information for the dynamic struct.
pub fn type_info(&self) -> TypeInfo {
self.rtti.clone().type_info()
}
}
Loading

0 comments on commit 6cbd6be

Please sign in to comment.