1
0

Continue value overhaul

This commit is contained in:
Jeff 2024-08-16 17:07:49 -04:00
parent 8bff39a7db
commit 8ae453add7
5 changed files with 745 additions and 1500 deletions

View File

@ -5,7 +5,7 @@ use std::{
use serde::{Deserialize, Serialize};
use crate::{Context, Identifier, Span, StructType, Type, Value};
use crate::{Context, FunctionType, Identifier, Span, StructType, Type, Value};
use super::{Node, Statement};
@ -236,7 +236,7 @@ impl Expression {
let invoker_type = invoker.return_type(context)?;
if let Type::Function { return_type, .. } = invoker_type {
if let Type::Function(FunctionType { return_type, .. }) = invoker_type {
return_type.map(|r#type| *r#type)
} else if let Type::Struct(_) = invoker_type {
Some(invoker_type)
@ -276,7 +276,7 @@ impl Expression {
}
ListExpression::Ordered(expressions) => {
if expressions.is_empty() {
return Some(Type::EmptyList);
return Some(Type::ListEmpty);
}
let item_type = expressions.last().unwrap().return_type(context)?;
@ -304,7 +304,6 @@ impl Expression {
LiteralExpression::Float(_) => Some(Type::Float),
LiteralExpression::Integer(_) => Some(Type::Integer),
LiteralExpression::String(_) => Some(Type::String),
LiteralExpression::Value(value) => Some(value.r#type()),
},
Expression::Loop(loop_expression) => match loop_expression.inner.as_ref() {
LoopExpression::For { block, .. } => block.inner.return_type(context),
@ -326,19 +325,19 @@ impl Expression {
StructExpression::Fields { name, fields } => {
let mut field_types = Vec::with_capacity(fields.len());
for (name, expression) in fields {
for (field_name, expression) in fields {
let r#type = expression.return_type(context)?;
field_types.push((name.inner.clone(), r#type));
field_types.push((field_name.inner.clone(), r#type));
}
Some(Type::Struct(StructType::Fields {
name: name.inner.clone(),
identifier: name.inner.clone(),
fields: field_types,
}))
}
StructExpression::Unit { name } => Some(Type::Struct(StructType::Unit {
name: name.inner.clone(),
identifier: name.inner.clone(),
})),
},
Expression::TupleAccess(tuple_access_expression) => {
@ -502,7 +501,6 @@ pub enum LiteralExpression {
Float(f64),
Integer(i64),
String(String),
Value(Value),
}
impl Display for LiteralExpression {
@ -512,7 +510,6 @@ impl Display for LiteralExpression {
LiteralExpression::Float(float) => write!(f, "{}", float),
LiteralExpression::Integer(integer) => write!(f, "{}", integer),
LiteralExpression::String(string) => write!(f, "{}", string),
LiteralExpression::Value(value) => write!(f, "{}", value),
}
}
}
@ -538,7 +535,6 @@ impl Ord for LiteralExpression {
left.cmp(right)
}
(LiteralExpression::String(left), LiteralExpression::String(right)) => left.cmp(right),
(LiteralExpression::Value(left), LiteralExpression::Value(right)) => left.cmp(right),
_ => unreachable!(),
}
}

View File

@ -36,7 +36,7 @@ pub use dust_error::DustError;
pub use identifier::Identifier;
pub use lexer::{lex, LexError, Lexer};
pub use parser::{parse, ParseError, Parser};
pub use r#type::{StructType, Type};
pub use r#type::{EnumType, FunctionType, StructType, Type};
pub use token::{Token, TokenKind, TokenOwned};
pub use value::{Struct, Value, ValueError};
pub use vm::{run, run_with_context, Vm, VmError};

View File

@ -10,19 +10,13 @@
//! library's "length" function does not care about the type of item in the list, only the list
//! itself. So the input is defined as `[any]`, i.e. `Type::ListOf(Box::new(Type::Any))`.
use std::{
collections::BTreeMap,
fmt::{self, Display, Formatter},
sync::Arc,
};
use serde::{Deserialize, Serialize};
use crate::Identifier;
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TypeConflict {
pub expected: Type,
pub actual: Type,
}
use crate::{value::Function, Identifier};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
/// Description of a kind of value.
@ -31,18 +25,11 @@ pub struct TypeConflict {
pub enum Type {
Any,
Boolean,
EmptyList,
Enum {
name: Identifier,
type_parameters: Option<Vec<Type>>,
variants: Vec<(Identifier, Option<Vec<Type>>)>,
},
Byte,
Character,
Enum(EnumType),
Float,
Function {
type_parameters: Option<Vec<Type>>,
value_parameters: Option<Vec<(Identifier, Type)>>,
return_type: Option<Box<Type>>,
},
Function(FunctionType),
Generic {
identifier: Identifier,
concrete_type: Option<Box<Type>>,
@ -52,14 +39,15 @@ pub enum Type {
item_type: Box<Type>,
length: usize,
},
ListEmpty,
ListOf {
item_type: Box<Type>,
},
Map(BTreeMap<Identifier, Type>),
Number,
Range,
String,
Struct(StructType),
Tuple(Vec<Type>),
}
impl Type {
@ -189,17 +177,26 @@ impl Type {
}
}
(
Type::Function {
Type::Function(FunctionType {
name: left_name,
type_parameters: left_type_parameters,
value_parameters: left_value_parameters,
return_type: left_return,
},
Type::Function {
}),
Type::Function(FunctionType {
name: right_name,
type_parameters: right_type_parameters,
value_parameters: right_value_parameters,
return_type: right_return,
},
}),
) => {
if left_name != right_name {
return Err(TypeConflict {
actual: other.clone(),
expected: self.clone(),
});
}
if left_return == right_return {
for (left_parameter, right_parameter) in left_type_parameters
.iter()
@ -228,11 +225,6 @@ impl Type {
return Ok(());
}
}
(Type::Map(left), Type::Map(right)) => {
if left == right {
return Ok(());
}
}
(Type::Number, Type::Number | Type::Integer | Type::Float)
| (Type::Integer | Type::Float, Type::Number) => {
return Ok(());
@ -252,29 +244,11 @@ impl Display for Type {
match self {
Type::Any => write!(f, "any"),
Type::Boolean => write!(f, "bool"),
Type::EmptyList => write!(f, "[]"),
Type::Enum { variants, .. } => {
write!(f, "enum ")?;
write!(f, " {{")?;
for (identifier, types) in variants {
writeln!(f, "{identifier}")?;
if let Some(types) = types {
write!(f, "(")?;
for r#type in types {
write!(f, "{}", r#type)?;
}
}
write!(f, ")")?;
}
write!(f, "}}")
}
Type::Byte => write!(f, "byte"),
Type::Character => write!(f, "char"),
Type::Enum(enum_type) => write!(f, "{enum_type}"),
Type::Float => write!(f, "float"),
Type::Function(function_type) => write!(f, "{function_type}"),
Type::Generic { concrete_type, .. } => {
match concrete_type.clone().map(|r#box| *r#box) {
Some(Type::Generic { identifier, .. }) => write!(f, "{identifier}"),
@ -284,82 +258,14 @@ impl Display for Type {
}
Type::Integer => write!(f, "int"),
Type::List { item_type, length } => write!(f, "[{item_type}; {length}]"),
Type::ListEmpty => write!(f, "[]"),
Type::ListOf { item_type } => write!(f, "[{item_type}]"),
Type::Map(map) => {
write!(f, "{{ ")?;
for (index, (key, r#type)) in map.iter().enumerate() {
write!(f, "{key}: {type}")?;
if index != map.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, " }}")
}
Type::Number => write!(f, "num"),
Type::Range => write!(f, "range"),
Type::String => write!(f, "str"),
Type::Function {
type_parameters,
value_parameters,
return_type,
} => {
write!(f, "fn ")?;
if let Some(type_parameters) = type_parameters {
write!(f, "<")?;
for identifier in type_parameters {
write!(f, "{}, ", identifier)?;
}
write!(f, ">")?;
}
write!(f, "(")?;
if let Some(value_parameters) = value_parameters {
for (identifier, r#type) in value_parameters {
write!(f, "{identifier}: {type}")?;
}
}
write!(f, ")")?;
if let Some(r#type) = return_type {
write!(f, " -> {type}")
} else {
Ok(())
}
}
Type::Struct(struct_type) => write!(f, "{struct_type}"),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum StructType {
Unit {
name: Identifier,
},
Tuple {
name: Identifier,
fields: Vec<Type>,
},
Fields {
name: Identifier,
fields: Vec<(Identifier, Type)>,
},
}
impl Display for StructType {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
StructType::Unit { name } => write!(f, "struct {name}"),
StructType::Tuple { name, fields } => {
write!(f, "struct {name}(")?;
Type::Tuple(fields) => {
write!(f, "(")?;
for (index, r#type) in fields.iter().enumerate() {
write!(f, "{type}")?;
@ -371,8 +277,94 @@ impl Display for StructType {
write!(f, ")")
}
StructType::Fields { name, fields } => {
write!(f, "struct {name} {{")?;
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FunctionType {
pub name: Identifier,
pub type_parameters: Option<Vec<Type>>,
pub value_parameters: Option<Vec<(Identifier, Type)>>,
pub return_type: Option<Box<Type>>,
}
impl Display for FunctionType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "fn ")?;
if let Some(type_parameters) = &self.type_parameters {
write!(f, "<")?;
for (index, type_parameter) in type_parameters.iter().enumerate() {
write!(f, "{type_parameter}")?;
if index != type_parameters.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ">")?;
}
write!(f, "(")?;
if let Some(value_parameters) = &self.value_parameters {
for (index, (identifier, r#type)) in value_parameters.iter().enumerate() {
write!(f, "{identifier}: {type}")?;
if index != value_parameters.len() - 1 {
write!(f, ", ")?;
}
}
}
write!(f, ")")?;
if let Some(return_type) = &self.return_type {
write!(f, " -> {return_type}")?;
}
Ok(())
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum StructType {
Unit {
identifier: Identifier,
},
Tuple {
identifier: Identifier,
fields: Vec<Type>,
},
Fields {
identifier: Identifier,
fields: Vec<(Identifier, Type)>,
},
}
impl Display for StructType {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
StructType::Unit { .. } => write!(f, "()"),
StructType::Tuple { fields, .. } => {
write!(f, "(")?;
for (index, r#type) in fields.iter().enumerate() {
write!(f, "{type}")?;
if index != fields.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
StructType::Fields {
identifier, fields, ..
} => {
write!(f, "{identifier} {{ ")?;
for (index, (identifier, r#type)) in fields.iter().enumerate() {
write!(f, "{identifier}: {type}")?;
@ -382,43 +374,64 @@ impl Display for StructType {
}
}
write!(f, "}}")
write!(f, " }}")
}
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EnumType {
name: Identifier,
variants: Vec<StructType>,
}
impl Display for EnumType {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.name)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TypeConflict {
pub expected: Type,
pub actual: Type,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_same_types() {
assert_eq!(Type::Any.check(&Type::Any), Ok(()));
assert_eq!(Type::Boolean.check(&Type::Boolean), Ok(()));
assert_eq!(Type::Float.check(&Type::Float), Ok(()));
assert_eq!(Type::Integer.check(&Type::Integer), Ok(()));
assert_eq!(
Type::List {
item_type: Box::new(Type::Boolean),
length: 42
fn check_type_any() {
let foo = Type::Any;
let bar = Type::Any;
foo.check(&bar).unwrap();
}
.check(&Type::List {
item_type: Box::new(Type::Boolean),
length: 42
}),
Ok(())
);
let mut map = BTreeMap::new();
#[test]
fn check_type_boolean() {
let foo = Type::Boolean;
let bar = Type::Boolean;
map.insert(Identifier::from("x"), Type::Integer);
map.insert(Identifier::from("y"), Type::String);
map.insert(Identifier::from("z"), Type::Map(map.clone()));
foo.check(&bar).unwrap();
}
assert_eq!(Type::Map(map.clone()).check(&Type::Map(map)), Ok(()));
assert_eq!(Type::Range.check(&Type::Range), Ok(()));
assert_eq!(Type::String.check(&Type::String), Ok(()));
#[test]
fn check_type_byte() {
let foo = Type::Byte;
let bar = Type::Byte;
foo.check(&bar).unwrap();
}
#[test]
fn check_type_character() {
let foo = Type::Character;
let bar = Type::Character;
foo.check(&bar).unwrap();
}
#[test]
@ -449,7 +462,6 @@ mod tests {
item_type: Box::new(Type::Integer),
length: 42,
},
Type::Map(BTreeMap::new()),
Type::Range,
Type::String,
];

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,6 @@
//! - `Vm` struct that can be used to run an abstract syntax tree
use std::{
fmt::{self, Display, Formatter},
ops::Range,
sync::{Arc, Mutex},
};
@ -151,14 +150,10 @@ impl Vm {
}
LetStatement::LetMut { identifier, value } => {
let value_position = value.position();
let value = self
let mutable_value = self
.run_expression(value, collect_garbage)?
.expect_value(value_position)?;
let mutable_value = value.to_mut().map_err(|error| VmError::ValueError {
error,
left_position: identifier.position,
right_position: value_position,
})?;
.expect_value(value_position)?
.into_mutable();
self.context.set_value(identifier.inner, mutable_value);