Vector specialization
This commit is contained in:
@@ -15,7 +15,7 @@ use crate::{
|
||||
},
|
||||
vm::{
|
||||
instruction::{Instruction, LocalId, MathInstruction, U},
|
||||
value::Value,
|
||||
value::{Value, Vector},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -625,6 +625,10 @@ impl<'a> LocalBlock<'a> {
|
||||
Ok(CompileValue::Nil)
|
||||
}
|
||||
|
||||
fn compile_vector(&mut self, vector: &Rc<Vector>) -> Result<CompileValue, CompileError> {
|
||||
Ok(CompileValue::Quote(Rc::new(Value::Vector(vector.clone()))))
|
||||
}
|
||||
|
||||
pub fn compile_expression(
|
||||
&mut self,
|
||||
expression: &Rc<Expression>,
|
||||
@@ -648,6 +652,7 @@ impl<'a> LocalBlock<'a> {
|
||||
Expression::While(cloop) => self.compile_while(cloop, break_label),
|
||||
Expression::Loop(cloop) => self.compile_loop(cloop),
|
||||
Expression::Progn(progn) => self.compile_progn(progn, break_label),
|
||||
Expression::Vector(vector) => self.compile_vector(vector),
|
||||
Expression::Return => self.compile_call_return(break_label),
|
||||
|
||||
Expression::SyntaxError(_) => unreachable!(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::vm::value::{ConsCell, Keyword, Value, ValueString};
|
||||
use crate::vm::value::{ConsCell, Keyword, Value, ValueString, Vector};
|
||||
|
||||
mod binding;
|
||||
mod call;
|
||||
@@ -40,6 +40,7 @@ pub enum Expression {
|
||||
While(WhileExpression),
|
||||
Loop(LoopExpression),
|
||||
Progn(PrognExpression),
|
||||
Vector(Rc<Vector>),
|
||||
Return,
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ impl Expression {
|
||||
Value::Boolean(value) => Rc::new(Self::BooleanLiteral(*value)),
|
||||
Value::Integer(value) => Rc::new(Self::IntegerLiteral(*value)),
|
||||
Value::String(value) => Rc::new(Self::StringLiteral(value.clone())),
|
||||
Value::Vector(_vector) => todo!(),
|
||||
Value::Vector(vector) => Rc::new(Self::Vector(vector.clone())),
|
||||
Value::Identifier(value) => Rc::new(Self::Identifier(value.clone())),
|
||||
Value::Quasi(_value) => todo!("{value}"),
|
||||
Value::Unquote(_value) => todo!("Unquote {_value}"),
|
||||
@@ -143,6 +144,7 @@ impl CollectErrors<ParseError> for Expression {
|
||||
Self::Loop(cloop) => cloop.collect_errors(errors),
|
||||
Self::Progn(progn) => progn.collect_errors(errors),
|
||||
Self::Nil
|
||||
| Self::Vector(_)
|
||||
| Self::Return
|
||||
| Self::IntegerLiteral(_)
|
||||
| Self::Identifier(_)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
use crate::vm::value::Value;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct VectorExpression {
|
||||
pub elements: Vec<Value>,
|
||||
}
|
||||
+14
-1
@@ -14,7 +14,7 @@ use nom::{
|
||||
sequence::{delimited, preceded},
|
||||
};
|
||||
|
||||
use crate::vm::value::{Keyword, Value};
|
||||
use crate::vm::value::{Keyword, Value, Vector};
|
||||
|
||||
struct IdentifierHead;
|
||||
struct IdentifierTail;
|
||||
@@ -295,9 +295,22 @@ fn parse_quote(input: &str) -> IResult<&str, Value> {
|
||||
.parse(input)
|
||||
}
|
||||
|
||||
fn parse_vector(input: &str) -> IResult<&str, Value> {
|
||||
delimited(
|
||||
char('['),
|
||||
many0(preceded(skip_comment_and_whitespace, parse_value)),
|
||||
preceded(skip_comment_and_whitespace, char(']')),
|
||||
)
|
||||
.map(Vector::from_iter)
|
||||
.map(Into::into)
|
||||
.map(Value::Vector)
|
||||
.parse(input)
|
||||
}
|
||||
|
||||
pub fn parse_value(input: &str) -> IResult<&str, Value> {
|
||||
alt((
|
||||
parse_list_or_nil,
|
||||
parse_vector,
|
||||
parse_boolean,
|
||||
parse_quote,
|
||||
parse_quasi,
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ impl MacroExpand for Value {
|
||||
let value = expand_quasiquote(value);
|
||||
value.macro_expand(vm, env, false)
|
||||
}
|
||||
Self::Vector(_) => todo!(),
|
||||
Self::Vector(vector) => Ok(Self::Vector(vector.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,44 @@ pub fn load(env: &mut Environment) {
|
||||
let result = Value::String(format!("{arg}").into());
|
||||
Ok(result)
|
||||
});
|
||||
env.defun_native("type", |vm, _, args| {
|
||||
let [arg] = args else {
|
||||
return Err(vm.error_at_ip(MachineErrorKind::InvalidArgument));
|
||||
};
|
||||
Ok(arg.typeid())
|
||||
});
|
||||
|
||||
// vectors
|
||||
env.defun_native("getv", |vm, _, args| {
|
||||
let [vec, index] = args else {
|
||||
return Err(vm.error_at_ip(MachineErrorKind::InvalidArgument));
|
||||
};
|
||||
let Value::Vector(vec) = vec else {
|
||||
return Err(vm.error_at_ip(MachineErrorKind::InvalidArgument));
|
||||
};
|
||||
let index = i64::try_from_value(index).map_err(|e| vm.error_at_ip(e))? as isize;
|
||||
let value = if index < 0 {
|
||||
todo!()
|
||||
} else {
|
||||
vec.value_at(index as usize).unwrap_or(Value::Nil)
|
||||
};
|
||||
Ok(value)
|
||||
});
|
||||
env.defun_native("setv", |vm, _, args| {
|
||||
let [vec, index, value] = args else {
|
||||
return Err(vm.error_at_ip(MachineErrorKind::InvalidArgument));
|
||||
};
|
||||
let Value::Vector(vec) = vec else {
|
||||
return Err(vm.error_at_ip(MachineErrorKind::InvalidArgument));
|
||||
};
|
||||
let index = i64::try_from_value(index).map_err(|e| vm.error_at_ip(e))? as isize;
|
||||
if index < 0 {
|
||||
todo!()
|
||||
} else {
|
||||
vec.set_value_at(index as usize, value.clone());
|
||||
}
|
||||
Ok(Value::Nil)
|
||||
});
|
||||
|
||||
// lists
|
||||
env.defun_native("car", |vm, _env, args| {
|
||||
|
||||
+41
-1
@@ -21,7 +21,7 @@ pub use cons::ConsCell;
|
||||
pub use keyword::Keyword;
|
||||
pub use native::{NativeFunction, NativeFunctionImpl, OpaqueValue};
|
||||
pub use string::ValueString;
|
||||
pub use vector::Vector;
|
||||
pub use vector::{Vector, VectorStorage};
|
||||
|
||||
pub use convert::{AnyFunction, TryFromValue};
|
||||
|
||||
@@ -85,6 +85,46 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn typeid(&self) -> Value {
|
||||
match self {
|
||||
Value::Nil | Value::Cons(_) => Value::list_or_nil([Value::Identifier("list".into())]),
|
||||
Value::Integer(_) => Value::list_or_nil([Value::Identifier("integer".into())]),
|
||||
Value::Vector(vector) => Value::list_or_nil([
|
||||
Value::Identifier("vector".into()),
|
||||
match &*vector.borrow() {
|
||||
VectorStorage::I8(_) => Value::Identifier("i8".into()),
|
||||
VectorStorage::I16(_) => Value::Identifier("i16".into()),
|
||||
VectorStorage::I32(_) => Value::Identifier("i32".into()),
|
||||
VectorStorage::I64(_) => Value::Identifier("i64".into()),
|
||||
VectorStorage::Any(_) => Value::Identifier("*".into()),
|
||||
},
|
||||
]),
|
||||
Value::Boolean(_) => Value::list_or_nil([Value::Identifier("boolean".into())]),
|
||||
Value::String(_) => Value::list_or_nil([Value::Identifier("string".into())]),
|
||||
Value::Quasi(value) => {
|
||||
Value::list_or_nil([Value::Identifier("quasi".into()), value.typeid()])
|
||||
}
|
||||
Value::Quote(value) => {
|
||||
Value::list_or_nil([Value::Identifier("quote".into()), value.typeid()])
|
||||
}
|
||||
Value::Unquote(value) => {
|
||||
Value::list_or_nil([Value::Identifier("unquote".into()), value.typeid()])
|
||||
}
|
||||
Value::NativeFunction(_) => {
|
||||
Value::list_or_nil([Value::Identifier("native-function".into())])
|
||||
}
|
||||
Value::BytecodeFunction(_) => {
|
||||
Value::list_or_nil([Value::Identifier("bytecode-function".into())])
|
||||
}
|
||||
Value::OpaqueValue(_) => Value::list_or_nil([Value::Identifier("opaque".into())]),
|
||||
Value::Keyword(keyword) => Value::list_or_nil([
|
||||
Value::Identifier("keyword".into()),
|
||||
Value::Identifier(format!("{keyword}").into()),
|
||||
]),
|
||||
Value::Identifier(_) => Value::list_or_nil([Value::Identifier("identifier".into())]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stringify(&self) -> Result<String, MachineErrorKind> {
|
||||
match self {
|
||||
Self::Integer(value) => Ok(format!("{value}")),
|
||||
|
||||
+328
-24
@@ -1,21 +1,23 @@
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
cell::{Ref, RefCell},
|
||||
fmt,
|
||||
hash::{Hash, Hasher},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use crate::vm::value::Value;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Vector(RefCell<Vec<Value>>);
|
||||
|
||||
impl Hash for Vector {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.borrow().hash(state);
|
||||
}
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub enum VectorStorage {
|
||||
I8(Vec<i8>),
|
||||
I16(Vec<i16>),
|
||||
I32(Vec<i32>),
|
||||
I64(Vec<i64>),
|
||||
Any(Vec<Value>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Vector(RefCell<VectorStorage>);
|
||||
|
||||
impl Vector {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.borrow().is_empty()
|
||||
@@ -24,31 +26,333 @@ impl Vector {
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.borrow().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Value> for Vector {
|
||||
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
|
||||
Self(RefCell::new(Vec::from_iter(iter)))
|
||||
pub fn borrow(&self) -> Ref<'_, VectorStorage> {
|
||||
self.0.borrow()
|
||||
}
|
||||
|
||||
pub fn value_at(&self, index: usize) -> Option<Value> {
|
||||
self.0.borrow().value_at(index)
|
||||
}
|
||||
pub fn set_value_at(&self, index: usize, value: Value) {
|
||||
self.0.borrow_mut().set_value_at(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Vector {
|
||||
type Target = RefCell<Vec<Value>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
impl Hash for Vector {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.borrow().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Vector {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "[")?;
|
||||
for (i, element) in self.0.borrow().iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
write!(f, "{element}")?;
|
||||
fmt::Display::fmt(&*self.0.borrow(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> FromIterator<A> for Vector
|
||||
where
|
||||
VectorStorage: FromIterator<A>,
|
||||
{
|
||||
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
|
||||
Self(RefCell::new(VectorStorage::from_iter(iter)))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! static_dispatch {
|
||||
([$input:expr] $value:ident => $body:expr) => {
|
||||
match $input {
|
||||
Self::I8($value) => $body,
|
||||
Self::I16($value) => $body,
|
||||
Self::I32($value) => $body,
|
||||
Self::I64($value) => $body,
|
||||
Self::Any($value) => $body,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! dispatch_integer_convert {
|
||||
($self:ident ($storage:ident, $value:ident) => $f:expr) => {
|
||||
match $self {
|
||||
Self::I8($storage) if let Ok($value) = i8::try_from($value) => {
|
||||
$f;
|
||||
}
|
||||
Self::I8($storage) if let Ok($value) = i16::try_from($value) => {
|
||||
let mut $storage = $storage.iter().copied().map(Into::into).collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::I16($storage);
|
||||
}
|
||||
Self::I8($storage) if let Ok($value) = i32::try_from($value) => {
|
||||
let mut $storage = $storage.iter().copied().map(Into::into).collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::I32($storage);
|
||||
}
|
||||
Self::I8($storage) => {
|
||||
let mut $storage = $storage.iter().copied().map(Into::into).collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::I64($storage);
|
||||
}
|
||||
Self::I16($storage) if let Ok($value) = i16::try_from($value) => {
|
||||
$f;
|
||||
}
|
||||
Self::I16($storage) if let Ok($value) = i32::try_from($value) => {
|
||||
let mut $storage = $storage.iter().copied().map(Into::into).collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::I32($storage);
|
||||
}
|
||||
Self::I16($storage) => {
|
||||
let mut $storage = $storage.iter().copied().map(Into::into).collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::I64($storage);
|
||||
}
|
||||
Self::I32($storage) if let Ok($value) = i32::try_from($value) => {
|
||||
$f;
|
||||
}
|
||||
Self::I32($storage) => {
|
||||
let mut $storage = $storage.iter().copied().map(Into::into).collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::I64($storage);
|
||||
}
|
||||
Self::I64($storage) => {
|
||||
$f;
|
||||
}
|
||||
Self::Any($storage) => {
|
||||
let $value = Value::Integer($value);
|
||||
$f;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! dispatch_any_convert {
|
||||
($self:ident ($storage:ident) => $f:expr) => {
|
||||
match $self {
|
||||
Self::I8($storage) => {
|
||||
let mut $storage = $storage
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Into::into)
|
||||
.map(Value::Integer)
|
||||
.collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::Any($storage);
|
||||
}
|
||||
Self::I16($storage) => {
|
||||
let mut $storage = $storage
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Into::into)
|
||||
.map(Value::Integer)
|
||||
.collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::Any($storage);
|
||||
}
|
||||
Self::I32($storage) => {
|
||||
let mut $storage = $storage
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Into::into)
|
||||
.map(Value::Integer)
|
||||
.collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::Any($storage);
|
||||
}
|
||||
Self::I64($storage) => {
|
||||
let mut $storage = $storage
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Value::Integer)
|
||||
.collect::<Vec<_>>();
|
||||
$f;
|
||||
*$self = Self::Any($storage);
|
||||
}
|
||||
Self::Any($storage) => {
|
||||
$f;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl VectorStorage {
|
||||
fn value_at(&self, index: usize) -> Option<Value> {
|
||||
match self {
|
||||
Self::I8(values) if let Some(value) = values.get(index).copied() => {
|
||||
Some(Value::Integer(value.into()))
|
||||
}
|
||||
Self::I16(values) if let Some(value) = values.get(index).copied() => {
|
||||
Some(Value::Integer(value.into()))
|
||||
}
|
||||
Self::I32(values) if let Some(value) = values.get(index).copied() => {
|
||||
Some(Value::Integer(value.into()))
|
||||
}
|
||||
Self::I64(values) if let Some(value) = values.get(index).copied() => {
|
||||
Some(Value::Integer(value))
|
||||
}
|
||||
Self::Any(values) if let Some(value) = values.get(index).cloned() => Some(value),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
static_dispatch!([self] vec => vec.len())
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
fn push(&mut self, value: Value) {
|
||||
match value {
|
||||
Value::Integer(value) => self.push_integer(value),
|
||||
value => match self {
|
||||
Self::Any(vec) => vec.push(value),
|
||||
_ => self.push_any(value),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn set_value_at(&mut self, index: usize, value: Value) {
|
||||
if index >= self.len() {
|
||||
return;
|
||||
}
|
||||
match value {
|
||||
Value::Integer(value) => self.set_integer(index, value),
|
||||
value => match self {
|
||||
Self::Any(vec) => vec[index] = value,
|
||||
_ => self.set_any(index, value),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn push_any(&mut self, value: Value) {
|
||||
dispatch_any_convert!(self (w) => {
|
||||
w.push(value);
|
||||
});
|
||||
}
|
||||
|
||||
fn set_any(&mut self, index: usize, value: Value) {
|
||||
dispatch_any_convert!(self (w) => {
|
||||
w[index] = value;
|
||||
});
|
||||
}
|
||||
|
||||
fn push_integer(&mut self, value: i64) {
|
||||
dispatch_integer_convert!(self (w, value) => {
|
||||
w.push(value);
|
||||
});
|
||||
}
|
||||
|
||||
fn set_integer(&mut self, index: usize, value: i64) {
|
||||
dispatch_integer_convert!(self (w, value) => {
|
||||
w[index] = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Value> for VectorStorage {
|
||||
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
|
||||
let mut accumulator = Self::I8(vec![]);
|
||||
for item in iter {
|
||||
accumulator.push(item);
|
||||
}
|
||||
accumulator
|
||||
}
|
||||
}
|
||||
|
||||
fn display_vector<T: fmt::Display>(value: &[T], f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for (i, value) in value.iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
write!(f, "{value}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl fmt::Display for VectorStorage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "[")?;
|
||||
match self {
|
||||
Self::I8(vec) => display_vector(vec, f),
|
||||
Self::I16(vec) => display_vector(vec, f),
|
||||
Self::I32(vec) => display_vector(vec, f),
|
||||
Self::I64(vec) => display_vector(vec, f),
|
||||
Self::Any(vec) => display_vector(vec, f),
|
||||
}?;
|
||||
write!(f, "]")
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_primitive_from_iter {
|
||||
($signed_ty:ty, $unsigned_ty:ty => $variant:ident) => {
|
||||
impl FromIterator<$signed_ty> for VectorStorage {
|
||||
fn from_iter<T: IntoIterator<Item = $signed_ty>>(iter: T) -> Self {
|
||||
Self::$variant(iter.into_iter().collect())
|
||||
}
|
||||
}
|
||||
impl FromIterator<$unsigned_ty> for VectorStorage {
|
||||
fn from_iter<T: IntoIterator<Item = $unsigned_ty>>(iter: T) -> Self {
|
||||
Self::$variant(iter.into_iter().map(|x| x as $signed_ty).collect())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_primitive_from_iter!(i8, u8 => I8);
|
||||
impl_primitive_from_iter!(i16, u16 => I16);
|
||||
impl_primitive_from_iter!(i32, u32 => I32);
|
||||
impl_primitive_from_iter!(i64, u64 => I64);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::vm::value::{Value, vector::VectorStorage};
|
||||
|
||||
#[test]
|
||||
fn test_vector_storage_from_iter() {
|
||||
let v = VectorStorage::from_iter([1i8, 2, 3, 4, 5, 6, 7]);
|
||||
assert_eq!(VectorStorage::I8(vec![1, 2, 3, 4, 5, 6, 7]), v);
|
||||
let v = VectorStorage::from_iter([1u8, 2, 3, 4, 5, 6, 7]);
|
||||
assert_eq!(VectorStorage::I8(vec![1, 2, 3, 4, 5, 6, 7]), v);
|
||||
let v = VectorStorage::from_iter([1i16, 2, 3, 4, 5, 6, 7]);
|
||||
assert_eq!(VectorStorage::I16(vec![1, 2, 3, 4, 5, 6, 7]), v);
|
||||
let v = VectorStorage::from_iter([1u16, 2, 3, 4, 5, 6, 7]);
|
||||
assert_eq!(VectorStorage::I16(vec![1, 2, 3, 4, 5, 6, 7]), v);
|
||||
let v = VectorStorage::from_iter([1i32, 2, 3, 4, 5, 6, 7]);
|
||||
assert_eq!(VectorStorage::I32(vec![1, 2, 3, 4, 5, 6, 7]), v);
|
||||
let v = VectorStorage::from_iter([1u32, 2, 3, 4, 5, 6, 7]);
|
||||
assert_eq!(VectorStorage::I32(vec![1, 2, 3, 4, 5, 6, 7]), v);
|
||||
let v = VectorStorage::from_iter([1i64, 2, 3, 4, 5, 6, 7]);
|
||||
assert_eq!(VectorStorage::I64(vec![1, 2, 3, 4, 5, 6, 7]), v);
|
||||
let v = VectorStorage::from_iter([1u64, 2, 3, 4, 5, 6, 7]);
|
||||
assert_eq!(VectorStorage::I64(vec![1, 2, 3, 4, 5, 6, 7]), v);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vector_unspecialize() {
|
||||
let mut v = VectorStorage::from_iter([1i8, 2, 3]);
|
||||
assert_eq!(VectorStorage::I8(vec![1, 2, 3]), v);
|
||||
v.push(Value::Integer(1234));
|
||||
assert_eq!(VectorStorage::I16(vec![1, 2, 3, 1234]), v);
|
||||
v.push(Value::Integer(12341234));
|
||||
assert_eq!(VectorStorage::I32(vec![1, 2, 3, 1234, 12341234]), v);
|
||||
v.push(Value::Integer(1234123412341234));
|
||||
assert_eq!(
|
||||
VectorStorage::I64(vec![1, 2, 3, 1234, 12341234, 1234123412341234]),
|
||||
v
|
||||
);
|
||||
v.push(Value::String("a".into()));
|
||||
assert_eq!(
|
||||
VectorStorage::Any(vec![
|
||||
Value::Integer(1),
|
||||
Value::Integer(2),
|
||||
Value::Integer(3),
|
||||
Value::Integer(1234),
|
||||
Value::Integer(12341234),
|
||||
Value::Integer(1234123412341234),
|
||||
Value::String("a".into())
|
||||
]),
|
||||
v
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user