1
0

Refactor values to use register pointers for complex values

This commit is contained in:
Jeff 2024-10-12 04:50:30 -04:00
parent 6e1ef77192
commit 9c612317dc
8 changed files with 369 additions and 1434 deletions

View File

@ -526,7 +526,10 @@ impl<'a> ChunkDisassembler<'a> {
for (index, value_option) in self.chunk.constants.iter().enumerate() { for (index, value_option) in self.chunk.constants.iter().enumerate() {
let value_display = value_option let value_display = value_option
.as_ref() .as_ref()
.map(|value| value.to_string()) .map(|value| match value {
Value::Primitive(value_data) => value_data.to_string(),
Value::Object(_) => "object".to_string(),
})
.unwrap_or("empty".to_string()); .unwrap_or("empty".to_string());
let trucated_length = 8; let trucated_length = 8;
let with_elipsis = trucated_length - 3; let with_elipsis = trucated_length - 3;
@ -540,35 +543,16 @@ impl<'a> ChunkDisassembler<'a> {
if let Some(function_disassembly) = if let Some(function_disassembly) =
value_option.as_ref().and_then(|value| match value { value_option.as_ref().and_then(|value| match value {
Value::Raw(value_data) => value_data.as_function().map(|function| { Value::Primitive(value_data) => value_data.as_function().map(|function| {
function function
.body() .body
.disassembler("function") .disassembler("function")
.styled(self.styled) .styled(self.styled)
.indent(self.indent + 1) .indent(self.indent + 1)
.width(self.width) .width(self.width)
.disassemble() .disassemble()
}), }),
Value::Reference(arc) => arc.as_function().map(|function| { Value::Object(_) => None,
function
.body()
.disassembler("function")
.styled(self.styled)
.indent(self.indent + 1)
.width(self.width)
.disassemble()
}),
Value::Mutable(rw_lock) => {
rw_lock.read().unwrap().as_function().map(|function| {
function
.body()
.disassembler("function")
.styled(self.styled)
.indent(self.indent + 1)
.width(self.width)
.disassemble()
})
}
}) })
{ {
push(&function_disassembly, false); push(&function_disassembly, false);

View File

@ -1,107 +0,0 @@
use std::{
collections::HashMap,
fmt::{self, Display, Formatter},
};
use serde::{Deserialize, Serialize};
use crate::{Identifier, Struct, StructType, TypeConflict, Value};
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Constructor {
pub struct_type: StructType,
}
impl Constructor {
pub fn construct_unit(&self) -> Result<Value, ConstructError> {
if let StructType::Unit { name } = &self.struct_type {
Ok(Value::r#struct(Struct::Unit { name: name.clone() }))
} else {
Err(ConstructError::ExpectedUnit)
}
}
pub fn construct_tuple(&self, fields: Vec<Value>) -> Result<Value, ConstructError> {
if let StructType::Tuple {
name: expected_name,
fields: expected_fields,
} = &self.struct_type
{
if fields.len() != expected_fields.len() {
return Err(ConstructError::FieldCountMismatch);
}
for (i, value) in fields.iter().enumerate() {
let expected_type = expected_fields.get(i).unwrap();
let actual_type = value.r#type();
expected_type.check(&actual_type)?;
}
Ok(Value::r#struct(Struct::Tuple {
name: expected_name.clone(),
fields,
}))
} else {
Err(ConstructError::ExpectedTuple)
}
}
pub fn construct_fields(
&self,
fields: HashMap<Identifier, Value>,
) -> Result<Value, ConstructError> {
if let StructType::Fields {
name: expected_name,
fields: expected_fields,
} = &self.struct_type
{
if fields.len() != expected_fields.len() {
return Err(ConstructError::FieldCountMismatch);
}
for (field_name, field_value) in fields.iter() {
let expected_type = expected_fields.get(field_name).unwrap();
let actual_type = field_value.r#type();
expected_type.check(&actual_type)?;
}
Ok(Value::r#struct(Struct::Fields {
name: expected_name.clone(),
fields,
}))
} else {
Err(ConstructError::ExpectedFields)
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum ConstructError {
FieldCountMismatch,
ExpectedUnit,
ExpectedTuple,
ExpectedFields,
TypeConflict(TypeConflict),
}
impl From<TypeConflict> for ConstructError {
fn from(conflict: TypeConflict) -> Self {
Self::TypeConflict(conflict)
}
}
impl Display for ConstructError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
ConstructError::FieldCountMismatch => write!(f, "Field count mismatch"),
ConstructError::ExpectedUnit => write!(f, "Expected unit struct"),
ConstructError::ExpectedTuple => write!(f, "Expected tuple struct"),
ConstructError::ExpectedFields => write!(f, "Expected fields struct"),
ConstructError::TypeConflict(TypeConflict { expected, actual }) => {
write!(f, "Type conflict: expected {}, got {}", expected, actual)
}
}
}
}

View File

@ -394,7 +394,7 @@ impl Instruction {
let constant = if let Some(chunk) = chunk { let constant = if let Some(chunk) = chunk {
match chunk.get_constant(constant_index, Span(0, 0)) { match chunk.get_constant(constant_index, Span(0, 0)) {
Ok(constant) => constant.to_string(), Ok(value) => value.to_string(),
Err(error) => format!("{error:?}"), Err(error) => format!("{error:?}"),
} }
} else { } else {

View File

@ -1,5 +1,4 @@
mod chunk; mod chunk;
mod constructor;
mod dust_error; mod dust_error;
mod identifier; mod identifier;
mod instruction; mod instruction;
@ -14,7 +13,6 @@ mod vm;
use std::fmt::Display; use std::fmt::Display;
pub use chunk::{Chunk, ChunkDisassembler, ChunkError, Local}; pub use chunk::{Chunk, ChunkDisassembler, ChunkError, Local};
pub use constructor::Constructor;
pub use dust_error::{AnnotatedError, DustError}; pub use dust_error::{AnnotatedError, DustError};
pub use identifier::Identifier; pub use identifier::Identifier;
pub use instruction::Instruction; pub use instruction::Instruction;
@ -23,7 +21,7 @@ pub use operation::Operation;
pub use parser::{parse, ParseError, Parser}; pub use parser::{parse, ParseError, Parser};
pub use r#type::{EnumType, FunctionType, RangeableType, StructType, Type, TypeConflict}; pub use r#type::{EnumType, FunctionType, RangeableType, StructType, Type, TypeConflict};
pub use token::{Token, TokenKind, TokenOwned}; pub use token::{Token, TokenKind, TokenOwned};
pub use value::{Enum, Function, Struct, Value, ValueError}; pub use value::{Function, Value, ValueError};
pub use vm::{run, Vm, VmError}; pub use vm::{run, Vm, VmError};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -17,7 +17,7 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{Constructor, Identifier}; use crate::Identifier;
/// Description of a kind of value. /// Description of a kind of value.
/// ///
@ -488,12 +488,6 @@ impl StructType {
StructType::Fields { name, .. } => name, StructType::Fields { name, .. } => name,
} }
} }
pub fn constructor(&self) -> Constructor {
Constructor {
struct_type: self.clone(),
}
}
} }
impl Display for StructType { impl Display for StructType {

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
use std::mem::replace; use std::mem::replace;
use crate::{ use crate::{
parse, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, Operation, Span, parse, value::Primitive, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction,
Value, ValueError, Operation, Span, Value, ValueError,
}; };
pub fn run(source: &str) -> Result<Option<Value>, DustError> { pub fn run(source: &str) -> Result<Option<Value>, DustError> {
@ -116,20 +116,9 @@ impl Vm {
let to_register = instruction.a(); let to_register = instruction.a();
let first_register = instruction.b(); let first_register = instruction.b();
let last_register = instruction.c(); let last_register = instruction.c();
let length = last_register - first_register + 1; let value = Value::list(first_register, last_register);
let mut list = Vec::with_capacity(length as usize);
for register_index in first_register..=last_register { self.set(to_register, value, position)?;
let value = match self.take(register_index, to_register, position) {
Ok(value) => value,
Err(VmError::EmptyRegister { .. }) => continue,
Err(error) => return Err(error),
};
list.push(value);
}
self.set(to_register, Value::list(list), position)?;
} }
Operation::DefineLocal => { Operation::DefineLocal => {
let from_register = instruction.a(); let from_register = instruction.a();
@ -211,10 +200,14 @@ impl Vm {
let register = instruction.a(); let register = instruction.a();
let test_value = instruction.c_as_boolean(); let test_value = instruction.c_as_boolean();
let value = self.get(register, position)?; let value = self.get(register, position)?;
let boolean = value.as_boolean().ok_or_else(|| VmError::ExpectedBoolean { let boolean = if let Value::Primitive(Primitive::Boolean(boolean)) = value {
found: value.clone(), *boolean
position, } else {
})?; return Err(VmError::ExpectedBoolean {
found: value.clone(),
position,
});
};
if boolean != test_value { if boolean != test_value {
self.ip += 1; self.ip += 1;
@ -226,12 +219,14 @@ impl Vm {
let test_value = instruction.c_as_boolean(); let test_value = instruction.c_as_boolean();
let borrowed_value = self.get(argument, position)?; let borrowed_value = self.get(argument, position)?;
let boolean = let boolean =
borrowed_value if let Value::Primitive(Primitive::Boolean(boolean)) = borrowed_value {
.as_boolean() *boolean
.ok_or_else(|| VmError::ExpectedBoolean { } else {
return Err(VmError::ExpectedBoolean {
found: borrowed_value.clone(), found: borrowed_value.clone(),
position, position,
})?; });
};
if boolean == test_value { if boolean == test_value {
let value = self.take(argument, to_register, position)?; let value = self.take(argument, to_register, position)?;
@ -248,15 +243,18 @@ impl Vm {
); );
let (left, right) = get_arguments(self, instruction, position)?; let (left, right) = get_arguments(self, instruction, position)?;
let equal_result = left
let boolean = left
.equal(right) .equal(right)
.map_err(|error| VmError::Value { error, position })? .map_err(|error| VmError::Value { error, position })?;
.as_boolean() let boolean =
.ok_or_else(|| VmError::ExpectedBoolean { if let Value::Primitive(Primitive::Boolean(boolean)) = equal_result {
found: left.clone(), boolean
position, } else {
})?; return Err(VmError::ExpectedBoolean {
found: equal_result.clone(),
position,
});
};
let compare_to = instruction.a_as_boolean(); let compare_to = instruction.a_as_boolean();
if boolean == compare_to { if boolean == compare_to {
@ -281,14 +279,18 @@ impl Vm {
); );
let (left, right) = get_arguments(self, instruction, position)?; let (left, right) = get_arguments(self, instruction, position)?;
let boolean = left let less_result = left
.less_than(right) .less_than(right)
.map_err(|error| VmError::Value { error, position })? .map_err(|error| VmError::Value { error, position })?;
.as_boolean() let boolean = if let Value::Primitive(Primitive::Boolean(boolean)) = less_result
.ok_or_else(|| VmError::ExpectedBoolean { {
found: left.clone(), boolean
} else {
return Err(VmError::ExpectedBoolean {
found: less_result.clone(),
position, position,
})?; });
};
let compare_to = instruction.a_as_boolean(); let compare_to = instruction.a_as_boolean();
if boolean == compare_to { if boolean == compare_to {
@ -313,14 +315,19 @@ impl Vm {
); );
let (left, right) = get_arguments(self, instruction, position)?; let (left, right) = get_arguments(self, instruction, position)?;
let boolean = left let less_or_equal_result = left
.less_than_or_equal(right) .less_than_or_equal(right)
.map_err(|error| VmError::Value { error, position })? .map_err(|error| VmError::Value { error, position })?;
.as_boolean() let boolean = if let Value::Primitive(Primitive::Boolean(boolean)) =
.ok_or_else(|| VmError::ExpectedBoolean { less_or_equal_result
found: left.clone(), {
boolean
} else {
return Err(VmError::ExpectedBoolean {
found: less_or_equal_result.clone(),
position, position,
})?; });
};
let compare_to = instruction.a_as_boolean(); let compare_to = instruction.a_as_boolean();
if boolean == compare_to { if boolean == compare_to {
@ -457,7 +464,7 @@ impl Vm {
}) })
} }
fn get(&self, index: u8, position: Span) -> Result<&Value, VmError> { pub fn get(&self, index: u8, position: Span) -> Result<&Value, VmError> {
let index = index as usize; let index = index as usize;
let register = self let register = self
.stack .stack

View File

@ -506,14 +506,7 @@ fn list() {
)), )),
); );
assert_eq!( assert_eq!(run(source), Ok(Some(Value::list(0, 2))));
run(source),
Ok(Some(Value::list(vec![
Value::integer(1),
Value::integer(2),
Value::integer(3)
])))
);
} }
#[test] #[test]
@ -553,13 +546,7 @@ fn list_with_complex_expression() {
)), )),
); );
assert_eq!( assert_eq!(run(source), Ok(Some(Value::list(0, 3))));
run(source),
Ok(Some(Value::list(vec![
Value::integer(1),
Value::integer(-15)
])))
);
} }
#[test] #[test]
@ -591,14 +578,7 @@ fn list_with_simple_expression() {
)), )),
); );
assert_eq!( assert_eq!(run(source), Ok(Some(Value::list(0, 2))));
run(source),
Ok(Some(Value::list(vec![
Value::integer(1),
Value::integer(5),
Value::integer(4)
])))
);
} }
#[test] #[test]