Vector specialization
This commit is contained in:
@@ -15,7 +15,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
vm::{
|
vm::{
|
||||||
instruction::{Instruction, LocalId, MathInstruction, U},
|
instruction::{Instruction, LocalId, MathInstruction, U},
|
||||||
value::Value,
|
value::{Value, Vector},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -625,6 +625,10 @@ impl<'a> LocalBlock<'a> {
|
|||||||
Ok(CompileValue::Nil)
|
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(
|
pub fn compile_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
expression: &Rc<Expression>,
|
expression: &Rc<Expression>,
|
||||||
@@ -648,6 +652,7 @@ impl<'a> LocalBlock<'a> {
|
|||||||
Expression::While(cloop) => self.compile_while(cloop, break_label),
|
Expression::While(cloop) => self.compile_while(cloop, break_label),
|
||||||
Expression::Loop(cloop) => self.compile_loop(cloop),
|
Expression::Loop(cloop) => self.compile_loop(cloop),
|
||||||
Expression::Progn(progn) => self.compile_progn(progn, break_label),
|
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::Return => self.compile_call_return(break_label),
|
||||||
|
|
||||||
Expression::SyntaxError(_) => unreachable!(),
|
Expression::SyntaxError(_) => unreachable!(),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::vm::value::{ConsCell, Keyword, Value, ValueString};
|
use crate::vm::value::{ConsCell, Keyword, Value, ValueString, Vector};
|
||||||
|
|
||||||
mod binding;
|
mod binding;
|
||||||
mod call;
|
mod call;
|
||||||
@@ -40,6 +40,7 @@ pub enum Expression {
|
|||||||
While(WhileExpression),
|
While(WhileExpression),
|
||||||
Loop(LoopExpression),
|
Loop(LoopExpression),
|
||||||
Progn(PrognExpression),
|
Progn(PrognExpression),
|
||||||
|
Vector(Rc<Vector>),
|
||||||
Return,
|
Return,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ impl Expression {
|
|||||||
Value::Boolean(value) => Rc::new(Self::BooleanLiteral(*value)),
|
Value::Boolean(value) => Rc::new(Self::BooleanLiteral(*value)),
|
||||||
Value::Integer(value) => Rc::new(Self::IntegerLiteral(*value)),
|
Value::Integer(value) => Rc::new(Self::IntegerLiteral(*value)),
|
||||||
Value::String(value) => Rc::new(Self::StringLiteral(value.clone())),
|
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::Identifier(value) => Rc::new(Self::Identifier(value.clone())),
|
||||||
Value::Quasi(_value) => todo!("{value}"),
|
Value::Quasi(_value) => todo!("{value}"),
|
||||||
Value::Unquote(_value) => todo!("Unquote {_value}"),
|
Value::Unquote(_value) => todo!("Unquote {_value}"),
|
||||||
@@ -143,6 +144,7 @@ impl CollectErrors<ParseError> for Expression {
|
|||||||
Self::Loop(cloop) => cloop.collect_errors(errors),
|
Self::Loop(cloop) => cloop.collect_errors(errors),
|
||||||
Self::Progn(progn) => progn.collect_errors(errors),
|
Self::Progn(progn) => progn.collect_errors(errors),
|
||||||
Self::Nil
|
Self::Nil
|
||||||
|
| Self::Vector(_)
|
||||||
| Self::Return
|
| Self::Return
|
||||||
| Self::IntegerLiteral(_)
|
| Self::IntegerLiteral(_)
|
||||||
| Self::Identifier(_)
|
| 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},
|
sequence::{delimited, preceded},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::vm::value::{Keyword, Value};
|
use crate::vm::value::{Keyword, Value, Vector};
|
||||||
|
|
||||||
struct IdentifierHead;
|
struct IdentifierHead;
|
||||||
struct IdentifierTail;
|
struct IdentifierTail;
|
||||||
@@ -295,9 +295,22 @@ fn parse_quote(input: &str) -> IResult<&str, Value> {
|
|||||||
.parse(input)
|
.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> {
|
pub fn parse_value(input: &str) -> IResult<&str, Value> {
|
||||||
alt((
|
alt((
|
||||||
parse_list_or_nil,
|
parse_list_or_nil,
|
||||||
|
parse_vector,
|
||||||
parse_boolean,
|
parse_boolean,
|
||||||
parse_quote,
|
parse_quote,
|
||||||
parse_quasi,
|
parse_quasi,
|
||||||
|
|||||||
+1
-1
@@ -75,7 +75,7 @@ impl MacroExpand for Value {
|
|||||||
let value = expand_quasiquote(value);
|
let value = expand_quasiquote(value);
|
||||||
value.macro_expand(vm, env, false)
|
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());
|
let result = Value::String(format!("{arg}").into());
|
||||||
Ok(result)
|
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
|
// lists
|
||||||
env.defun_native("car", |vm, _env, args| {
|
env.defun_native("car", |vm, _env, args| {
|
||||||
|
|||||||
+41
-1
@@ -21,7 +21,7 @@ pub use cons::ConsCell;
|
|||||||
pub use keyword::Keyword;
|
pub use keyword::Keyword;
|
||||||
pub use native::{NativeFunction, NativeFunctionImpl, OpaqueValue};
|
pub use native::{NativeFunction, NativeFunctionImpl, OpaqueValue};
|
||||||
pub use string::ValueString;
|
pub use string::ValueString;
|
||||||
pub use vector::Vector;
|
pub use vector::{Vector, VectorStorage};
|
||||||
|
|
||||||
pub use convert::{AnyFunction, TryFromValue};
|
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> {
|
pub fn stringify(&self) -> Result<String, MachineErrorKind> {
|
||||||
match self {
|
match self {
|
||||||
Self::Integer(value) => Ok(format!("{value}")),
|
Self::Integer(value) => Ok(format!("{value}")),
|
||||||
|
|||||||
+328
-24
@@ -1,21 +1,23 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::{Ref, RefCell},
|
||||||
fmt,
|
fmt,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
ops::Deref,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::vm::value::Value;
|
use crate::vm::value::Value;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Vector(RefCell<Vec<Value>>);
|
pub enum VectorStorage {
|
||||||
|
I8(Vec<i8>),
|
||||||
impl Hash for Vector {
|
I16(Vec<i16>),
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
I32(Vec<i32>),
|
||||||
self.0.borrow().hash(state);
|
I64(Vec<i64>),
|
||||||
}
|
Any(Vec<Value>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct Vector(RefCell<VectorStorage>);
|
||||||
|
|
||||||
impl Vector {
|
impl Vector {
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.borrow().is_empty()
|
self.0.borrow().is_empty()
|
||||||
@@ -24,31 +26,333 @@ impl Vector {
|
|||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.borrow().len()
|
self.0.borrow().len()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl FromIterator<Value> for Vector {
|
pub fn borrow(&self) -> Ref<'_, VectorStorage> {
|
||||||
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
|
self.0.borrow()
|
||||||
Self(RefCell::new(Vec::from_iter(iter)))
|
}
|
||||||
|
|
||||||
|
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 {
|
impl Hash for Vector {
|
||||||
type Target = RefCell<Vec<Value>>;
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.0.borrow().hash(state);
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Vector {
|
impl fmt::Display for Vector {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "[")?;
|
fmt::Display::fmt(&*self.0.borrow(), f)
|
||||||
for (i, element) in self.0.borrow().iter().enumerate() {
|
}
|
||||||
if i != 0 {
|
}
|
||||||
write!(f, " ")?;
|
|
||||||
}
|
impl<A> FromIterator<A> for Vector
|
||||||
write!(f, "{element}")?;
|
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, "]")
|
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