Compare commits
1 Commits
master
...
feature/io
| Author | SHA1 | Date | |
|---|---|---|---|
| db5b1dba7b |
@@ -0,0 +1,5 @@
|
|||||||
|
;; vi:ft=lisp:sw=2:ts=2
|
||||||
|
|
||||||
|
(let (f (fopen (car *args*)))
|
||||||
|
(fwrite (fread f))
|
||||||
|
)
|
||||||
+19
-1
@@ -9,7 +9,7 @@ use crate::{
|
|||||||
syntax::{
|
syntax::{
|
||||||
CallExpression, CondExpression, DefmacroExpression, DefunExpression, Expression,
|
CallExpression, CondExpression, DefmacroExpression, DefunExpression, Expression,
|
||||||
FunctionBody, IfExpression, LambdaExpression, LetExpression, LoopExpression,
|
FunctionBody, IfExpression, LambdaExpression, LetExpression, LoopExpression,
|
||||||
PrognExpression, SetqExpression, WhileExpression,
|
PrognExpression, SetqExpression, VectorExpression, WhileExpression,
|
||||||
},
|
},
|
||||||
value::{BuiltinFunction, CompileConstant, CompileValue},
|
value::{BuiltinFunction, CompileConstant, CompileValue},
|
||||||
},
|
},
|
||||||
@@ -625,6 +625,23 @@ impl<'a> LocalBlock<'a> {
|
|||||||
Ok(CompileValue::Nil)
|
Ok(CompileValue::Nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compile_vector(
|
||||||
|
&mut self,
|
||||||
|
vector: &VectorExpression,
|
||||||
|
break_label: Option<u32>,
|
||||||
|
) -> Result<CompileValue, CompileError> {
|
||||||
|
for expression in vector.elements.iter().rev() {
|
||||||
|
let value = self.compile_expression(expression, break_label)?;
|
||||||
|
self.compile_push(value)?;
|
||||||
|
}
|
||||||
|
self.compile_push(CompileValue::Global("vector".into()))?;
|
||||||
|
let Some(count) = U::new(vector.elements.len() as u32) else {
|
||||||
|
todo!()
|
||||||
|
};
|
||||||
|
self.function.emit(Instruction::Call(count));
|
||||||
|
Ok(CompileValue::Stack)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn compile_expression(
|
pub fn compile_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
expression: &Rc<Expression>,
|
expression: &Rc<Expression>,
|
||||||
@@ -638,6 +655,7 @@ impl<'a> LocalBlock<'a> {
|
|||||||
Expression::Identifier(identifier) => self.compile_identifier(identifier),
|
Expression::Identifier(identifier) => self.compile_identifier(identifier),
|
||||||
Expression::Lambda(lambda) => self.compile_lambda(lambda),
|
Expression::Lambda(lambda) => self.compile_lambda(lambda),
|
||||||
Expression::Defun(defun) => self.compile_defun(defun),
|
Expression::Defun(defun) => self.compile_defun(defun),
|
||||||
|
Expression::Vector(vector) => self.compile_vector(vector, break_label),
|
||||||
Expression::Call(call) => self.compile_call(call, break_label),
|
Expression::Call(call) => self.compile_call(call, break_label),
|
||||||
Expression::If(condition) => self.compile_if(condition, break_label),
|
Expression::If(condition) => self.compile_if(condition, break_label),
|
||||||
Expression::Cond(condition) => self.compile_cond(condition, break_label),
|
Expression::Cond(condition) => self.compile_cond(condition, break_label),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ mod function;
|
|||||||
mod lambda;
|
mod lambda;
|
||||||
mod loops;
|
mod loops;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
mod vector;
|
||||||
|
|
||||||
pub use binding::*;
|
pub use binding::*;
|
||||||
pub use call::*;
|
pub use call::*;
|
||||||
@@ -19,6 +20,7 @@ pub use function::*;
|
|||||||
pub use lambda::*;
|
pub use lambda::*;
|
||||||
pub use loops::*;
|
pub use loops::*;
|
||||||
pub use macros::*;
|
pub use macros::*;
|
||||||
|
pub use vector::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
@@ -40,6 +42,7 @@ pub enum Expression {
|
|||||||
While(WhileExpression),
|
While(WhileExpression),
|
||||||
Loop(LoopExpression),
|
Loop(LoopExpression),
|
||||||
Progn(PrognExpression),
|
Progn(PrognExpression),
|
||||||
|
Vector(VectorExpression),
|
||||||
Return,
|
Return,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +70,6 @@ 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::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}"),
|
||||||
@@ -116,6 +118,9 @@ impl Expression {
|
|||||||
_ => Self::map_or(CallExpression::parse(cons, value), Expression::Call),
|
_ => Self::map_or(CallExpression::parse(cons, value), Expression::Call),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Value::Vector(vector) => {
|
||||||
|
Rc::new(Self::Vector(VectorExpression::parse(&vector.borrow())))
|
||||||
|
}
|
||||||
Value::Keyword(_) => todo!(),
|
Value::Keyword(_) => todo!(),
|
||||||
Value::NativeFunction(_) | Value::BytecodeFunction(_) | Value::OpaqueValue(_) => {
|
Value::NativeFunction(_) | Value::BytecodeFunction(_) | Value::OpaqueValue(_) => {
|
||||||
todo!()
|
todo!()
|
||||||
@@ -142,6 +147,7 @@ impl CollectErrors<ParseError> for Expression {
|
|||||||
Self::While(cloop) => cloop.collect_errors(errors),
|
Self::While(cloop) => cloop.collect_errors(errors),
|
||||||
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::Vector(vector) => vector.collect_errors(errors),
|
||||||
Self::Nil
|
Self::Nil
|
||||||
| Self::Return
|
| Self::Return
|
||||||
| Self::IntegerLiteral(_)
|
| Self::IntegerLiteral(_)
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
compile::{Expression, ParseError, syntax::CollectErrors},
|
||||||
|
vm::value::Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct VectorExpression {
|
||||||
|
pub elements: Vec<Rc<Expression>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VectorExpression {
|
||||||
|
pub fn parse(values: &[Value]) -> Self {
|
||||||
|
Self {
|
||||||
|
elements: values.iter().map(Expression::parse_inner).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CollectErrors<ParseError> for VectorExpression {
|
||||||
|
fn collect_errors(&self, errors: &mut Vec<ParseError>) -> bool {
|
||||||
|
let mut r = false;
|
||||||
|
for expr in self.elements.iter() {
|
||||||
|
r |= expr.collect_errors(errors);
|
||||||
|
}
|
||||||
|
r
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-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;
|
||||||
@@ -179,6 +179,17 @@ fn parse_list_or_nil(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)
|
||||||
|
.map(Value::from)
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_boolean(input: &str) -> IResult<&str, Value> {
|
fn parse_boolean(input: &str) -> IResult<&str, Value> {
|
||||||
map(
|
map(
|
||||||
alt((
|
alt((
|
||||||
@@ -298,6 +309,7 @@ fn parse_quote(input: &str) -> IResult<&str, Value> {
|
|||||||
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,
|
||||||
|
|||||||
+5
-1
@@ -75,7 +75,11 @@ 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(Value::Vector(
|
||||||
|
vector
|
||||||
|
.try_map(|value| value.macro_expand(vm, env, false))?
|
||||||
|
.into(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
fs::File,
|
||||||
|
io::{Read, Write, stdin, stdout},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::vm::{
|
||||||
|
env::Environment,
|
||||||
|
value::{Value, Vector},
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FileStream {
|
||||||
|
Closed,
|
||||||
|
File(File),
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Stream {
|
||||||
|
Stdin,
|
||||||
|
Stdout,
|
||||||
|
File(RefCell<FileStream>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stream {
|
||||||
|
fn read_bytes(&self, data: &mut [u8]) -> Option<usize> {
|
||||||
|
let result = match self {
|
||||||
|
Self::Stdin => stdin().read(data),
|
||||||
|
Self::Stdout => return None,
|
||||||
|
Self::File(file) => match &mut *file.borrow_mut() {
|
||||||
|
FileStream::File(file) => file.read(data),
|
||||||
|
FileStream::Closed => return None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
result.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_bytes(&self, data: &[u8]) -> Option<usize> {
|
||||||
|
match self {
|
||||||
|
Self::Stdin => None,
|
||||||
|
Self::Stdout => stdout().write(data).ok(),
|
||||||
|
Self::File(file) => match &mut *file.borrow_mut() {
|
||||||
|
FileStream::File(file) => file.write(data).ok(),
|
||||||
|
FileStream::Closed => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn load(env: &mut Environment) {
|
||||||
|
env.set_global_value("*stdin*", Value::opaque(Stream::Stdin));
|
||||||
|
env.set_global_value("*stdout*", Value::opaque(Stream::Stdout));
|
||||||
|
|
||||||
|
env.defun_native("fopen", |_, _, args| {
|
||||||
|
let [path] = args else {
|
||||||
|
todo!();
|
||||||
|
};
|
||||||
|
let Value::String(path) = path else { todo!() };
|
||||||
|
match File::open(&**path) {
|
||||||
|
Ok(file) => Ok(Value::opaque(Stream::File(RefCell::new(FileStream::File(
|
||||||
|
file,
|
||||||
|
))))),
|
||||||
|
Err(_) => Ok(Value::Nil),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
env.defun_native("fclose", |vm, _, args| {
|
||||||
|
let [stream] = args else { todo!() };
|
||||||
|
let stream = stream
|
||||||
|
.as_opaque::<Stream>()
|
||||||
|
.map_err(|e| vm.error_at_ip(e))?;
|
||||||
|
if let Stream::File(file) = stream {
|
||||||
|
*file.borrow_mut() = FileStream::Closed;
|
||||||
|
}
|
||||||
|
Ok(Value::Nil)
|
||||||
|
});
|
||||||
|
env.defun_native("fread", |vm, _, args| {
|
||||||
|
let stream = match args {
|
||||||
|
[] => &Stream::Stdin,
|
||||||
|
[stream] => stream
|
||||||
|
.as_opaque::<Stream>()
|
||||||
|
.map_err(|e| vm.error_at_ip(e))?,
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
let mut buffer = [0; 256];
|
||||||
|
let count = stream.read_bytes(&mut buffer);
|
||||||
|
match count {
|
||||||
|
Some(len) => {
|
||||||
|
let vector = Vector::from_iter(&buffer[..len]);
|
||||||
|
Ok(Value::Vector(vector.into()))
|
||||||
|
}
|
||||||
|
None => Ok(Value::Nil),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
env.defun_native("fwrite", |vm, _, args| {
|
||||||
|
let (stream, data) = match args {
|
||||||
|
[data] => (&Stream::Stdout, data),
|
||||||
|
[stream, data] => (
|
||||||
|
stream
|
||||||
|
.as_opaque::<Stream>()
|
||||||
|
.map_err(|e| vm.error_at_ip(e))?,
|
||||||
|
data,
|
||||||
|
),
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match data {
|
||||||
|
Value::Vector(vector) => {
|
||||||
|
let bytes = vector.to_bytes().unwrap();
|
||||||
|
match stream.write_bytes(&bytes) {
|
||||||
|
Some(count) => Ok(Value::Integer(count as i64)),
|
||||||
|
None => Ok(Value::Nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::String(value) => match stream.write_bytes(value.as_bytes()) {
|
||||||
|
Some(count) => Ok(Value::Integer(count as i64)),
|
||||||
|
None => Ok(Value::Nil),
|
||||||
|
},
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -267,3 +267,25 @@ pub(crate) fn builtin_cmp_le(
|
|||||||
) -> Result<Value, MachineError> {
|
) -> Result<Value, MachineError> {
|
||||||
builtin_cmp(vm, args, CompareOperation::Le)
|
builtin_cmp(vm, args, CompareOperation::Le)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn load(env: &mut Environment) {
|
||||||
|
// math
|
||||||
|
env.defun_native("+", builtin_add);
|
||||||
|
env.defun_native("-", builtin_sub);
|
||||||
|
env.defun_native("*", builtin_mul);
|
||||||
|
env.defun_native("%", builtin_mod);
|
||||||
|
env.defun_native("/", builtin_div);
|
||||||
|
|
||||||
|
env.defun_native("&&", builtin_and);
|
||||||
|
env.defun_native("||", builtin_or);
|
||||||
|
env.defun_native("&", builtin_bitwise_and);
|
||||||
|
env.defun_native("|", builtin_bitwise_or);
|
||||||
|
env.defun_native("^", builtin_bitwise_xor);
|
||||||
|
|
||||||
|
env.defun_native(">", builtin_cmp_gt);
|
||||||
|
env.defun_native("<", builtin_cmp_lt);
|
||||||
|
env.defun_native("=", builtin_cmp_eq);
|
||||||
|
env.defun_native("/=", builtin_cmp_ne);
|
||||||
|
env.defun_native(">=", builtin_cmp_ge);
|
||||||
|
env.defun_native("<=", builtin_cmp_le);
|
||||||
|
}
|
||||||
|
|||||||
+9
-20
@@ -6,33 +6,18 @@ use crate::{
|
|||||||
util::IteratorExt,
|
util::IteratorExt,
|
||||||
vm::{
|
vm::{
|
||||||
env::Environment,
|
env::Environment,
|
||||||
value::{AnyFunction, ConsCell, Keyword, TryFromValue, Value, ValueString},
|
value::{AnyFunction, ConsCell, Keyword, TryFromValue, Value, ValueString, Vector},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod io;
|
||||||
mod math;
|
mod math;
|
||||||
|
|
||||||
pub(crate) use math::*;
|
pub(crate) use math::*;
|
||||||
|
|
||||||
pub fn load(env: &mut Environment) {
|
pub fn load(env: &mut Environment) {
|
||||||
// math
|
math::load(env);
|
||||||
env.defun_native("+", builtin_add);
|
io::load(env);
|
||||||
env.defun_native("-", builtin_sub);
|
|
||||||
env.defun_native("*", builtin_mul);
|
|
||||||
env.defun_native("%", builtin_mod);
|
|
||||||
env.defun_native("/", builtin_div);
|
|
||||||
|
|
||||||
env.defun_native("&&", builtin_and);
|
|
||||||
env.defun_native("||", builtin_or);
|
|
||||||
env.defun_native("&", builtin_bitwise_and);
|
|
||||||
env.defun_native("|", builtin_bitwise_or);
|
|
||||||
env.defun_native("^", builtin_bitwise_xor);
|
|
||||||
|
|
||||||
env.defun_native(">", builtin_cmp_gt);
|
|
||||||
env.defun_native("<", builtin_cmp_lt);
|
|
||||||
env.defun_native("=", builtin_cmp_eq);
|
|
||||||
env.defun_native("/=", builtin_cmp_ne);
|
|
||||||
env.defun_native(">=", builtin_cmp_ge);
|
|
||||||
env.defun_native("<=", builtin_cmp_le);
|
|
||||||
|
|
||||||
// conversion
|
// conversion
|
||||||
env.defun_native("string->int", |vm, _, args| {
|
env.defun_native("string->int", |vm, _, args| {
|
||||||
@@ -51,6 +36,10 @@ 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("vector", |_, _, args| {
|
||||||
|
let vector = Vector::from_iter(args.iter().cloned());
|
||||||
|
Ok(Value::Vector(vector.into()))
|
||||||
|
});
|
||||||
|
|
||||||
// lists
|
// lists
|
||||||
env.defun_native("car", |vm, _env, args| {
|
env.defun_native("car", |vm, _env, args| {
|
||||||
|
|||||||
@@ -39,6 +39,12 @@ macro_rules! impl_primitive_value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&$t> for Value {
|
||||||
|
fn from(value: &$t) -> Self {
|
||||||
|
Self::Integer(*value as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFromValue<'_> for $t {
|
impl TryFromValue<'_> for $t {
|
||||||
fn try_from_value(value: &Value) -> Result<Self, MachineErrorKind> {
|
fn try_from_value(value: &Value) -> Result<Self, MachineErrorKind> {
|
||||||
match value {
|
match value {
|
||||||
|
|||||||
+13
-1
@@ -1,4 +1,4 @@
|
|||||||
use std::{fmt, hash::Hash, rc::Rc};
|
use std::{any::Any, fmt, hash::Hash, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
compile::{ExpectedWhat, ExpectedWhere, ParseError, ParseErrorKind},
|
compile::{ExpectedWhat, ExpectedWhere, ParseError, ParseErrorKind},
|
||||||
@@ -78,6 +78,12 @@ impl Value {
|
|||||||
matches!(self, Self::Nil)
|
matches!(self, Self::Nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn opaque<T: 'static>(value: T) -> Self {
|
||||||
|
let value: Rc<dyn Any> = Rc::new(value);
|
||||||
|
let opaque = OpaqueValue::from(value);
|
||||||
|
Self::OpaqueValue(opaque)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_opaque<T: 'static>(&self) -> Result<&T, MachineErrorKind> {
|
pub fn as_opaque<T: 'static>(&self) -> Result<&T, MachineErrorKind> {
|
||||||
match self {
|
match self {
|
||||||
Self::OpaqueValue(opaque) => opaque.cast(),
|
Self::OpaqueValue(opaque) => opaque.cast(),
|
||||||
@@ -135,6 +141,12 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vector> for Value {
|
||||||
|
fn from(value: Vector) -> Self {
|
||||||
|
Self::Vector(Rc::new(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Value {
|
impl fmt::Display for Value {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
+29
-4
@@ -5,7 +5,10 @@ use std::{
|
|||||||
ops::Deref,
|
ops::Deref,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::vm::value::Value;
|
use crate::{
|
||||||
|
error::MachineErrorKind,
|
||||||
|
vm::value::{TryFromValue, Value},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Vector(RefCell<Vec<Value>>);
|
pub struct Vector(RefCell<Vec<Value>>);
|
||||||
@@ -16,7 +19,21 @@ impl Hash for Vector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec<Value>> for Vector {
|
||||||
|
fn from(value: Vec<Value>) -> Self {
|
||||||
|
Self(RefCell::new(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Vector {
|
impl Vector {
|
||||||
|
pub fn try_map<E, F: FnMut(&Value) -> Result<Value, E>>(&self, map: F) -> Result<Vector, E> {
|
||||||
|
self.0.borrow().iter().map(map).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_bytes(&self) -> Result<Vec<u8>, MachineErrorKind> {
|
||||||
|
self.0.borrow().iter().map(u8::try_from_value).collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.borrow().is_empty()
|
self.0.borrow().is_empty()
|
||||||
}
|
}
|
||||||
@@ -26,9 +43,17 @@ impl Vector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromIterator<Value> for Vector {
|
// impl FromIterator<Value> for Vector {
|
||||||
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
|
// fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
|
||||||
Self(RefCell::new(Vec::from_iter(iter)))
|
// Self(RefCell::new(Vec::from_iter(iter)))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl<T: Into<Value>> FromIterator<T> for Vector {
|
||||||
|
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
||||||
|
Self(RefCell::new(Vec::from_iter(
|
||||||
|
iter.into_iter().map(Into::into),
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user