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() {
let value_display = value_option
.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());
let trucated_length = 8;
let with_elipsis = trucated_length - 3;
@ -540,35 +543,16 @@ impl<'a> ChunkDisassembler<'a> {
if let Some(function_disassembly) =
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
.body()
.body
.disassembler("function")
.styled(self.styled)
.indent(self.indent + 1)
.width(self.width)
.disassemble()
}),
Value::Reference(arc) => arc.as_function().map(|function| {
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()
})
}
Value::Object(_) => None,
})
{
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 {
match chunk.get_constant(constant_index, Span(0, 0)) {
Ok(constant) => constant.to_string(),
Ok(value) => value.to_string(),
Err(error) => format!("{error:?}"),
}
} else {

View File

@ -1,5 +1,4 @@
mod chunk;
mod constructor;
mod dust_error;
mod identifier;
mod instruction;
@ -14,7 +13,6 @@ mod vm;
use std::fmt::Display;
pub use chunk::{Chunk, ChunkDisassembler, ChunkError, Local};
pub use constructor::Constructor;
pub use dust_error::{AnnotatedError, DustError};
pub use identifier::Identifier;
pub use instruction::Instruction;
@ -23,7 +21,7 @@ pub use operation::Operation;
pub use parser::{parse, ParseError, Parser};
pub use r#type::{EnumType, FunctionType, RangeableType, StructType, Type, TypeConflict};
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};
use serde::{Deserialize, Serialize};

View File

@ -17,7 +17,7 @@ use std::{
use serde::{Deserialize, Serialize};
use crate::{Constructor, Identifier};
use crate::Identifier;
/// Description of a kind of value.
///
@ -488,12 +488,6 @@ impl StructType {
StructType::Fields { name, .. } => name,
}
}
pub fn constructor(&self) -> Constructor {
Constructor {
struct_type: self.clone(),
}
}
}
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 crate::{
parse, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, Operation, Span,
Value, ValueError,
parse, value::Primitive, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction,
Operation, Span, Value, ValueError,
};
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
@ -116,20 +116,9 @@ impl Vm {
let to_register = instruction.a();
let first_register = instruction.b();
let last_register = instruction.c();
let length = last_register - first_register + 1;
let mut list = Vec::with_capacity(length as usize);
let value = Value::list(first_register, last_register);
for register_index in first_register..=last_register {
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)?;
self.set(to_register, value, position)?;
}
Operation::DefineLocal => {
let from_register = instruction.a();
@ -211,10 +200,14 @@ impl Vm {
let register = instruction.a();
let test_value = instruction.c_as_boolean();
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 {
*boolean
} else {
return Err(VmError::ExpectedBoolean {
found: value.clone(),
position,
})?;
});
};
if boolean != test_value {
self.ip += 1;
@ -226,12 +219,14 @@ impl Vm {
let test_value = instruction.c_as_boolean();
let borrowed_value = self.get(argument, position)?;
let boolean =
borrowed_value
.as_boolean()
.ok_or_else(|| VmError::ExpectedBoolean {
if let Value::Primitive(Primitive::Boolean(boolean)) = borrowed_value {
*boolean
} else {
return Err(VmError::ExpectedBoolean {
found: borrowed_value.clone(),
position,
})?;
});
};
if boolean == test_value {
let value = self.take(argument, to_register, position)?;
@ -248,15 +243,18 @@ impl Vm {
);
let (left, right) = get_arguments(self, instruction, position)?;
let boolean = left
let equal_result = left
.equal(right)
.map_err(|error| VmError::Value { error, position })?
.as_boolean()
.ok_or_else(|| VmError::ExpectedBoolean {
found: left.clone(),
.map_err(|error| VmError::Value { error, position })?;
let boolean =
if let Value::Primitive(Primitive::Boolean(boolean)) = equal_result {
boolean
} else {
return Err(VmError::ExpectedBoolean {
found: equal_result.clone(),
position,
})?;
});
};
let compare_to = instruction.a_as_boolean();
if boolean == compare_to {
@ -281,14 +279,18 @@ impl Vm {
);
let (left, right) = get_arguments(self, instruction, position)?;
let boolean = left
let less_result = left
.less_than(right)
.map_err(|error| VmError::Value { error, position })?
.as_boolean()
.ok_or_else(|| VmError::ExpectedBoolean {
found: left.clone(),
.map_err(|error| VmError::Value { error, position })?;
let boolean = if let Value::Primitive(Primitive::Boolean(boolean)) = less_result
{
boolean
} else {
return Err(VmError::ExpectedBoolean {
found: less_result.clone(),
position,
})?;
});
};
let compare_to = instruction.a_as_boolean();
if boolean == compare_to {
@ -313,14 +315,19 @@ impl Vm {
);
let (left, right) = get_arguments(self, instruction, position)?;
let boolean = left
let less_or_equal_result = left
.less_than_or_equal(right)
.map_err(|error| VmError::Value { error, position })?
.as_boolean()
.ok_or_else(|| VmError::ExpectedBoolean {
found: left.clone(),
.map_err(|error| VmError::Value { error, position })?;
let boolean = if let Value::Primitive(Primitive::Boolean(boolean)) =
less_or_equal_result
{
boolean
} else {
return Err(VmError::ExpectedBoolean {
found: less_or_equal_result.clone(),
position,
})?;
});
};
let compare_to = instruction.a_as_boolean();
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 register = self
.stack

View File

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