1
0

Remimplement features

This commit is contained in:
Jeff 2024-08-20 00:15:19 -04:00
parent 0fd19a623d
commit e3d821a1c3
11 changed files with 797 additions and 472 deletions

1
Cargo.lock generated
View File

@ -165,6 +165,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"dust-lang", "dust-lang",
"env_logger",
] ]
[[package]] [[package]]

View File

@ -16,8 +16,7 @@ use crate::{
MapExpression, Node, OperatorExpression, RangeExpression, Span, Statement, MapExpression, Node, OperatorExpression, RangeExpression, Span, Statement,
StructDefinition, StructExpression, TupleAccessExpression, StructDefinition, StructExpression, TupleAccessExpression,
}, },
parse, Context, DustError, Expression, FieldsStructType, Identifier, StructType, TupleType, parse, Context, DustError, Expression, Identifier, StructType, Type,
Type,
}; };
/// Analyzes the abstract syntax tree for errors. /// Analyzes the abstract syntax tree for errors.
@ -85,62 +84,44 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(&expression_node.inner)?; self.analyze_expression(&expression_node.inner)?;
} }
Statement::Let(let_statement) => match &let_statement.inner { Statement::Let(let_statement) => match &let_statement.inner {
LetStatement::Let { identifier, value } => { LetStatement::Let { identifier, value }
let type_option = value.return_type(self.context); | LetStatement::LetMut { identifier, value } => {
self.analyze_expression(value)?;
if let Some(r#type) = type_option { let r#type = value.return_type(self.context);
self.context.set_type(
if let Some(r#type) = r#type {
self.context.set_variable_type(
identifier.inner.clone(), identifier.inner.clone(),
r#type, r#type,
identifier.position, identifier.position,
); );
} else { } else {
return Err(AnalysisError::ExpectedValue { return Err(AnalysisError::ExpectedValueFromExpression {
actual: statement.clone(), actual: value.clone(),
}); });
} }
self.analyze_expression(value)?;
} }
LetStatement::LetMut { identifier, value } => { LetStatement::LetType { .. } => todo!(),
let type_option = value.return_type(self.context); LetStatement::LetMutType { .. } => todo!(),
if let Some(r#type) = type_option {
self.context.set_type(
identifier.inner.clone(),
r#type,
identifier.position,
);
} else {
return Err(AnalysisError::ExpectedValue {
actual: statement.clone(),
});
}
self.analyze_expression(value)?;
}
LetStatement::LetType {
identifier,
r#type,
value,
} => todo!(),
LetStatement::LetMutType {
identifier,
r#type,
value,
} => todo!(),
}, },
Statement::StructDefinition(struct_definition) => { Statement::StructDefinition(struct_definition) => {
let (name, struct_type) = match &struct_definition.inner { let (name, struct_type) = match &struct_definition.inner {
StructDefinition::Unit { name } => { StructDefinition::Unit { name } => (
(name.inner.clone(), Type::Struct(StructType::Unit)) name,
} Type::Struct(StructType::Unit {
name: name.inner.clone(),
}),
),
StructDefinition::Tuple { name, items } => { StructDefinition::Tuple { name, items } => {
let fields = items.iter().map(|item| item.inner.clone()).collect(); let fields = items.iter().map(|item| item.inner.clone()).collect();
( (
name.inner.clone(), name,
Type::Struct(StructType::Tuple(TupleType { fields })), Type::Struct(StructType::Tuple {
name: name.inner.clone(),
fields,
}),
) )
} }
StructDefinition::Fields { name, fields } => { StructDefinition::Fields { name, fields } => {
@ -152,14 +133,16 @@ impl<'a> Analyzer<'a> {
.collect(); .collect();
( (
name.inner.clone(), name,
Type::Struct(StructType::Fields(FieldsStructType { fields })), Type::Struct(StructType::Fields {
name: name.inner.clone(),
fields,
}),
) )
} }
}; };
self.context todo!("Set constructor")
.set_type(name, struct_type, struct_definition.position);
} }
} }
@ -179,24 +162,19 @@ impl<'a> Analyzer<'a> {
} }
} }
Expression::FieldAccess(field_access_expression) => { Expression::FieldAccess(field_access_expression) => {
let FieldAccessExpression { container, .. } = let FieldAccessExpression { container, field } =
field_access_expression.inner.as_ref(); field_access_expression.inner.as_ref();
self.context
.update_last_position(&field.inner, field.position);
self.analyze_expression(container)?; self.analyze_expression(container)?;
} }
Expression::Grouped(expression) => { Expression::Grouped(expression) => {
self.analyze_expression(expression.inner.as_ref())?; self.analyze_expression(expression.inner.as_ref())?;
} }
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let found = self self.context
.context
.update_last_position(&identifier.inner, identifier.position); .update_last_position(&identifier.inner, identifier.position);
if !found {
return Err(AnalysisError::UndefinedVariable {
identifier: identifier.clone(),
});
}
} }
Expression::If(if_expression) => self.analyze_if(&if_expression.inner)?, Expression::If(if_expression) => self.analyze_if(&if_expression.inner)?,
Expression::List(list_expression) => match list_expression.inner.as_ref() { Expression::List(list_expression) => match list_expression.inner.as_ref() {
@ -256,6 +234,31 @@ impl<'a> Analyzer<'a> {
} => { } => {
self.analyze_expression(assignee)?; self.analyze_expression(assignee)?;
self.analyze_expression(modifier)?; self.analyze_expression(modifier)?;
let expected_type = assignee.return_type(self.context);
let actual_type = modifier.return_type(self.context);
if expected_type.is_none() {
return Err(AnalysisError::ExpectedValueFromExpression {
actual: assignee.clone(),
});
}
if actual_type.is_none() {
return Err(AnalysisError::ExpectedValueFromExpression {
actual: modifier.clone(),
});
}
if let (Some(expected_type), Some(actual_type)) = (expected_type, actual_type) {
expected_type.check(&actual_type).map_err(|type_conflct| {
AnalysisError::TypeConflict {
actual_expression: modifier.clone(),
actual_type,
expected: expected_type,
}
})?;
}
} }
OperatorExpression::ErrorPropagation(_) => todo!(), OperatorExpression::ErrorPropagation(_) => todo!(),
OperatorExpression::Negation(expression) => { OperatorExpression::Negation(expression) => {
@ -285,30 +288,14 @@ impl<'a> Analyzer<'a> {
}, },
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
StructExpression::Unit { name } => { StructExpression::Unit { name } => {
let found = self todo!("Update constructor position");
.context
.update_last_position(&name.inner, name.position);
if !found {
return Err(AnalysisError::UndefinedType {
identifier: name.clone(),
});
}
} }
StructExpression::Fields { name, fields } => { StructExpression::Fields { name, fields } => {
let found = self todo!("Update constructor position");
.context
.update_last_position(&name.inner, name.position);
if !found { // for (_, expression) in fields {
return Err(AnalysisError::UndefinedType { // self.analyze_expression(expression)?;
identifier: name.clone(), // }
});
}
for (_, expression) in fields {
self.analyze_expression(expression)?;
}
} }
}, },
Expression::TupleAccess(tuple_access) => { Expression::TupleAccess(tuple_access) => {
@ -390,9 +377,12 @@ pub enum AnalysisError {
ExpectedMap { ExpectedMap {
actual: Statement, actual: Statement,
}, },
ExpectedValue { ExpectedValueFromStatement {
actual: Statement, actual: Statement,
}, },
ExpectedValueFromExpression {
actual: Expression,
},
ExpectedValueArgumentCount { ExpectedValueArgumentCount {
expected: usize, expected: usize,
actual: usize, actual: usize,
@ -405,7 +395,7 @@ pub enum AnalysisError {
length: usize, length: usize,
}, },
TypeConflict { TypeConflict {
actual_statement: Statement, actual_expression: Expression,
actual_type: Type, actual_type: Type,
expected: Type, expected: Type,
}, },
@ -436,12 +426,13 @@ impl AnalysisError {
AnalysisError::ExpectedIntegerOrRange { actual } => actual.position(), AnalysisError::ExpectedIntegerOrRange { actual } => actual.position(),
AnalysisError::ExpectedList { actual } => actual.position(), AnalysisError::ExpectedList { actual } => actual.position(),
AnalysisError::ExpectedMap { actual } => actual.position(), AnalysisError::ExpectedMap { actual } => actual.position(),
AnalysisError::ExpectedValue { actual } => actual.position(), AnalysisError::ExpectedValueFromExpression { actual } => actual.position(),
AnalysisError::ExpectedValueFromStatement { actual } => actual.position(),
AnalysisError::ExpectedValueArgumentCount { position, .. } => *position, AnalysisError::ExpectedValueArgumentCount { position, .. } => *position,
AnalysisError::IndexOutOfBounds { index, .. } => index.position(), AnalysisError::IndexOutOfBounds { index, .. } => index.position(),
AnalysisError::TypeConflict { AnalysisError::TypeConflict {
actual_statement, .. actual_expression, ..
} => actual_statement.position(), } => actual_expression.position(),
AnalysisError::UndefinedField { identifier, .. } => identifier.position(), AnalysisError::UndefinedField { identifier, .. } => identifier.position(),
AnalysisError::UndefinedType { identifier } => identifier.position, AnalysisError::UndefinedType { identifier } => identifier.position,
AnalysisError::UndefinedVariable { identifier } => identifier.position, AnalysisError::UndefinedVariable { identifier } => identifier.position,
@ -470,8 +461,15 @@ impl Display for AnalysisError {
} }
AnalysisError::ExpectedList { actual } => write!(f, "Expected list, found {}", actual), AnalysisError::ExpectedList { actual } => write!(f, "Expected list, found {}", actual),
AnalysisError::ExpectedMap { actual } => write!(f, "Expected map, found {}", actual), AnalysisError::ExpectedMap { actual } => write!(f, "Expected map, found {}", actual),
AnalysisError::ExpectedValue { actual, .. } => { AnalysisError::ExpectedValueFromExpression { actual, .. } => {
write!(f, "Expected value, found {}", actual) write!(
f,
"Expected expression to produce a value, found {}",
actual
)
}
AnalysisError::ExpectedValueFromStatement { actual, .. } => {
write!(f, "Expected statement to produce a value, found {}", actual)
} }
AnalysisError::ExpectedValueArgumentCount { AnalysisError::ExpectedValueArgumentCount {
expected, actual, .. expected, actual, ..
@ -487,7 +485,7 @@ impl Display for AnalysisError {
index_value, list, length index_value, list, length
), ),
AnalysisError::TypeConflict { AnalysisError::TypeConflict {
actual_statement, actual_expression: actual_statement,
actual_type, actual_type,
expected, expected,
} => { } => {
@ -521,18 +519,27 @@ impl Display for AnalysisError {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{Identifier, Value};
use super::*; use super::*;
#[test] #[test]
fn add_assign_wrong_type() { fn add_assign_wrong_type() {
let source = " let source = "
a = 1 let mut a = 1;
a += 1.0 a += 1.0
"; ";
assert_eq!(analyze(source), todo!()); assert_eq!(
analyze(source),
Err(DustError::AnalysisError {
analysis_error: AnalysisError::TypeConflict {
actual_expression: Expression::literal(1.0, (45, 48)),
actual_type: Type::Float,
expected: Type::Integer,
},
source,
})
);
} }
#[test] #[test]
@ -542,7 +549,17 @@ mod tests {
a -= 1.0 a -= 1.0
"; ";
assert_eq!(analyze(source), todo!()); assert_eq!(
analyze(source),
Err(DustError::AnalysisError {
analysis_error: AnalysisError::TypeConflict {
actual_expression: Expression::literal(1.0, (45, 48)),
actual_type: Type::Float,
expected: Type::Integer,
},
source,
})
);
} }
#[test] #[test]

View File

@ -6,9 +6,7 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{Context, FunctionType, Identifier, RangeableType, StructType, Type};
Context, FieldsStructType, FunctionType, Identifier, RangeableType, StructType, TupleType, Type,
};
use super::{Node, Span, Statement}; use super::{Node, Span, Statement};
@ -268,17 +266,17 @@ impl Expression {
pub fn return_type(&self, context: &Context) -> Option<Type> { pub fn return_type(&self, context: &Context) -> Option<Type> {
match self { match self {
Expression::Block(block_expression) => { Expression::Block(block_expression) => {
block_expression.inner.as_ref().return_type(context) Some(block_expression.inner.return_type(context)?)
} }
Expression::Call(call_expression) => { Expression::Call(call_expression) => {
let CallExpression { invoker, .. } = call_expression.inner.as_ref(); let CallExpression { invoker, .. } = call_expression.inner.as_ref();
let invoker_type = invoker.return_type(context)?; let invoker_type = invoker.return_type(context);
if let Type::Function(FunctionType { return_type, .. }) = invoker_type { if let Some(Type::Function(FunctionType { return_type, .. })) = invoker_type {
return_type.map(|r#type| *r#type) return_type.map(|r#type| *r#type)
} else if let Type::Struct(_) = invoker_type { } else if let Some(Type::Struct(_)) = invoker_type {
Some(invoker_type) invoker_type
} else { } else {
None None
} }
@ -287,11 +285,9 @@ impl Expression {
let FieldAccessExpression { container, field } = let FieldAccessExpression { container, field } =
field_access_expression.inner.as_ref(); field_access_expression.inner.as_ref();
let container_type = container.return_type(context)?; let container_type = container.return_type(context);
if let Type::Struct(StructType::Fields(FieldsStructType { fields, .. })) = if let Some(Type::Struct(StructType::Fields { fields, .. })) = container_type {
container_type
{
fields fields
.into_iter() .into_iter()
.find(|(name, _)| name == &field.inner) .find(|(name, _)| name == &field.inner)
@ -301,12 +297,13 @@ impl Expression {
} }
} }
Expression::Grouped(expression) => expression.inner.return_type(context), Expression::Grouped(expression) => expression.inner.return_type(context),
Expression::Identifier(identifier) => context.get_type(&identifier.inner), Expression::Identifier(identifier) => context.get_variable_type(&identifier.inner),
Expression::If(if_expression) => match if_expression.inner.as_ref() { Expression::If(if_expression) => {
return match if_expression.inner.as_ref() {
IfExpression::If { .. } => None, IfExpression::If { .. } => None,
IfExpression::IfElse { if_block, .. } => if_block.inner.return_type(context), IfExpression::IfElse { if_block, .. } => if_block.inner.return_type(context),
}, }
}
Expression::List(list_expression) => match list_expression.inner.as_ref() { Expression::List(list_expression) => match list_expression.inner.as_ref() {
ListExpression::AutoFill { repeat_operand, .. } => { ListExpression::AutoFill { repeat_operand, .. } => {
let item_type = repeat_operand.return_type(context)?; let item_type = repeat_operand.return_type(context)?;
@ -396,7 +393,7 @@ impl Expression {
}) })
} }
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
StructExpression::Fields { fields, .. } => { StructExpression::Fields { name, fields } => {
let mut types = HashMap::with_capacity(fields.len()); let mut types = HashMap::with_capacity(fields.len());
for (field, expression) in fields { for (field, expression) in fields {
@ -405,17 +402,20 @@ impl Expression {
types.insert(field.inner.clone(), r#type); types.insert(field.inner.clone(), r#type);
} }
Some(Type::Struct(StructType::Fields(FieldsStructType { Some(Type::Struct(StructType::Fields {
name: name.inner.clone(),
fields: types, fields: types,
}))) }))
} }
StructExpression::Unit { .. } => Some(Type::Struct(StructType::Unit)), StructExpression::Unit { name } => Some(Type::Struct(StructType::Unit {
name: name.inner.clone(),
})),
}, },
Expression::TupleAccess(tuple_access_expression) => { Expression::TupleAccess(tuple_access_expression) => {
let TupleAccessExpression { tuple, index } = tuple_access_expression.inner.as_ref(); let TupleAccessExpression { tuple, index } = tuple_access_expression.inner.as_ref();
let tuple_value = tuple.return_type(context)?; let tuple_value = tuple.return_type(context)?;
if let Type::Tuple(TupleType { fields }) = tuple_value { if let Type::Tuple(fields) = tuple_value {
fields.get(index.inner).cloned() fields.get(index.inner).cloned()
} else { } else {
None None
@ -944,12 +944,13 @@ pub enum BlockExpression {
impl BlockExpression { impl BlockExpression {
fn return_type(&self, context: &Context) -> Option<Type> { fn return_type(&self, context: &Context) -> Option<Type> {
match self { match self {
BlockExpression::Async(statements) => statements BlockExpression::Async(statements) | BlockExpression::Sync(statements) => {
.last() if let Some(statement) = statements.last() {
.and_then(|statement| statement.return_type(context)), statement.return_type(context)
BlockExpression::Sync(statements) => statements } else {
.last() None
.and_then(|statement| statement.return_type(context)), }
}
} }
} }
} }

View File

@ -19,17 +19,6 @@ impl Statement {
Statement::StructDefinition(Node::new(struct_definition, position)) Statement::StructDefinition(Node::new(struct_definition, position))
} }
pub fn return_type(&self, context: &Context) -> Option<Type> {
match self {
Statement::Expression(expression) => expression.return_type(context),
Statement::ExpressionNullified(expression_node) => {
expression_node.inner.return_type(context)
}
Statement::Let(_) => None,
Statement::StructDefinition(_) => None,
}
}
pub fn position(&self) -> Span { pub fn position(&self) -> Span {
match self { match self {
Statement::Expression(expression) => expression.position(), Statement::Expression(expression) => expression.position(),
@ -38,6 +27,15 @@ impl Statement {
Statement::StructDefinition(definition) => definition.position, Statement::StructDefinition(definition) => definition.position,
} }
} }
pub fn return_type(&self, context: &Context) -> Option<Type> {
match self {
Statement::Expression(expression) => expression.return_type(context),
Statement::ExpressionNullified(expression) => None,
Statement::Let(_) => None,
Statement::StructDefinition(_) => None,
}
}
} }
impl Display for Statement { impl Display for Statement {

View File

@ -22,7 +22,7 @@ impl Context {
} }
/// Creates a deep copy of another context. /// Creates a deep copy of another context.
pub fn with_variables_from(other: &Self) -> Self { pub fn with_data_from(other: &Self) -> Self {
Self { Self {
variables: Arc::new(RwLock::new(other.variables.read().unwrap().clone())), variables: Arc::new(RwLock::new(other.variables.read().unwrap().clone())),
} }
@ -44,7 +44,7 @@ impl Context {
} }
/// Returns the type of the variable with the given identifier. /// Returns the type of the variable with the given identifier.
pub fn get_type(&self, identifier: &Identifier) -> Option<Type> { pub fn get_variable_type(&self, identifier: &Identifier) -> Option<Type> {
match self.variables.read().unwrap().get(identifier) { match self.variables.read().unwrap().get(identifier) {
Some((VariableData::Type(r#type), _)) => Some(r#type.clone()), Some((VariableData::Type(r#type), _)) => Some(r#type.clone()),
Some((VariableData::Value(value), _)) => Some(value.r#type()), Some((VariableData::Value(value), _)) => Some(value.r#type()),
@ -61,7 +61,7 @@ impl Context {
} }
/// Returns the value of the variable with the given identifier. /// Returns the value of the variable with the given identifier.
pub fn get_value(&self, identifier: &Identifier) -> Option<Value> { pub fn get_variable_value(&self, identifier: &Identifier) -> Option<Value> {
match self.variables.read().unwrap().get(identifier) { match self.variables.read().unwrap().get(identifier) {
Some((VariableData::Value(value), _)) => Some(value.clone()), Some((VariableData::Value(value), _)) => Some(value.clone()),
_ => None, _ => None,
@ -69,7 +69,7 @@ impl Context {
} }
/// Sets a variable to a type, with a position given for garbage collection. /// Sets a variable to a type, with a position given for garbage collection.
pub fn set_type(&self, identifier: Identifier, r#type: Type, position: Span) { pub fn set_variable_type(&self, identifier: Identifier, r#type: Type, position: Span) {
log::trace!("Setting {identifier} to type {type} at {position:?}"); log::trace!("Setting {identifier} to type {type} at {position:?}");
self.variables self.variables
@ -79,7 +79,7 @@ impl Context {
} }
/// Sets a variable to a value. /// Sets a variable to a value.
pub fn set_value(&self, identifier: Identifier, value: Value) { pub fn set_variable_value(&self, identifier: Identifier, value: Value) {
log::trace!("Setting {identifier} to value {value}"); log::trace!("Setting {identifier} to value {value}");
let mut variables = self.variables.write().unwrap(); let mut variables = self.variables.write().unwrap();

View File

@ -314,21 +314,12 @@ impl<'src> Parser<'src> {
} }
let expression = self.parse_expression(0)?; let expression = self.parse_expression(0)?;
let end = self.current_position.1;
let is_nullified = if let Token::Semicolon = self.current_token { if let Token::Semicolon = self.current_token {
let position = (start_position.0, self.current_position.1);
self.next_token()?; self.next_token()?;
true
} else {
matches!(
expression,
Expression::Block(_) | Expression::Loop(_) | Expression::If(_)
)
};
if is_nullified {
let position = (start_position.0, end);
Ok(Statement::ExpressionNullified(Node::new( Ok(Statement::ExpressionNullified(Node::new(
expression, position, expression, position,
))) )))
@ -446,10 +437,9 @@ impl<'src> Parser<'src> {
} }
if let Token::LeftCurlyBrace = self.current_token { if let Token::LeftCurlyBrace = self.current_token {
let name = Node::new(identifier, start_position);
self.next_token()?; self.next_token()?;
let name = Node::new(identifier, start_position);
let mut fields = Vec::new(); let mut fields = Vec::new();
loop { loop {
@ -1274,16 +1264,12 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
statements: [Statement::ExpressionNullified(Node::new( statements: [Statement::Expression(Expression::block(
Expression::block(
BlockExpression::Async(vec![ BlockExpression::Async(vec![
Statement::ExpressionNullified(Node::new( Statement::ExpressionNullified(Node::new(
Expression::operator( Expression::operator(
OperatorExpression::Assignment { OperatorExpression::Assignment {
assignee: Expression::identifier( assignee: Expression::identifier(Identifier::new("x"), (8, 9)),
Identifier::new("x"),
(8, 9)
),
value: Expression::literal(42, (12, 14)), value: Expression::literal(42, (12, 14)),
}, },
(8, 14) (8, 14)
@ -1292,18 +1278,13 @@ mod tests {
)), )),
Statement::Expression(Expression::operator( Statement::Expression(Expression::operator(
OperatorExpression::Assignment { OperatorExpression::Assignment {
assignee: Expression::identifier( assignee: Expression::identifier(Identifier::new("y"), (16, 17)),
Identifier::new("y"),
(16, 17)
),
value: Expression::literal(4.0, (20, 23)), value: Expression::literal(4.0, (20, 23)),
}, },
(16, 23) (16, 23)
)) ))
]), ]),
(0, 25) (0, 25)
),
(0, 25)
))] ))]
.into() .into()
}) })
@ -1597,8 +1578,7 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::ExpressionNullified(Node::new( Statement::Expression(Expression::r#if(
Expression::r#if(
IfExpression::If { IfExpression::If {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
@ -1609,8 +1589,6 @@ mod tests {
) )
}, },
(0, 10) (0, 10)
),
(0, 10)
)) ))
])) ]))
); );
@ -1623,8 +1601,7 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::ExpressionNullified(Node::new( Statement::Expression(Expression::r#if(
Expression::r#if(
IfExpression::IfElse { IfExpression::IfElse {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
@ -1641,8 +1618,6 @@ mod tests {
)) ))
}, },
(0, 21) (0, 21)
),
(0, 21)
)) ))
])) ]))
); );
@ -1655,8 +1630,7 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::ExpressionNullified(Node::new( Statement::Expression(Expression::r#if(
Expression::r#if(
IfExpression::IfElse { IfExpression::IfElse {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
@ -1667,10 +1641,7 @@ mod tests {
), ),
r#else: ElseExpression::If(Node::new( r#else: ElseExpression::If(Node::new(
Box::new(IfExpression::IfElse { Box::new(IfExpression::IfElse {
condition: Expression::identifier( condition: Expression::identifier(Identifier::new("z"), (19, 20)),
Identifier::new("z"),
(19, 20)
),
if_block: Node::new( if_block: Node::new(
BlockExpression::Sync(vec![Statement::Expression( BlockExpression::Sync(vec![Statement::Expression(
Expression::identifier(Identifier::new("a"), (23, 24)) Expression::identifier(Identifier::new("a"), (23, 24))
@ -1688,8 +1659,6 @@ mod tests {
)), )),
}, },
(0, 37) (0, 37)
),
(0, 37)
)) ))
])) ]))
) )
@ -1702,8 +1671,7 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::ExpressionNullified(Node::new( Statement::Expression(Expression::while_loop(
Expression::while_loop(
Expression::operator( Expression::operator(
OperatorExpression::Comparison { OperatorExpression::Comparison {
left: Expression::identifier(Identifier::new("x"), (6, 7)), left: Expression::identifier(Identifier::new("x"), (6, 7)),
@ -1713,24 +1681,17 @@ mod tests {
(6, 12) (6, 12)
), ),
Node::new( Node::new(
BlockExpression::Sync(vec![Statement::Expression( BlockExpression::Sync(vec![Statement::Expression(Expression::operator(
Expression::operator(
OperatorExpression::CompoundAssignment { OperatorExpression::CompoundAssignment {
assignee: Expression::identifier( assignee: Expression::identifier(Identifier::new("x"), (15, 16)),
Identifier::new("x"),
(15, 16)
),
operator: Node::new(MathOperator::Add, (17, 19)), operator: Node::new(MathOperator::Add, (17, 19)),
modifier: Expression::literal(1, (20, 21)), modifier: Expression::literal(1, (20, 21)),
}, },
(15, 21) (15, 21)
) ))]),
)]),
(13, 23) (13, 23)
), ),
(0, 23) (0, 23)
),
(0, 23)
)) ))
])) ]))
) )
@ -1781,8 +1742,7 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::ExpressionNullified(Node::new( Statement::Expression(Expression::block(
Expression::block(
BlockExpression::Sync(vec![Statement::Expression(Expression::operator( BlockExpression::Sync(vec![Statement::Expression(Expression::operator(
OperatorExpression::Math { OperatorExpression::Math {
left: Expression::literal(40, (2, 4)), left: Expression::literal(40, (2, 4)),
@ -1792,8 +1752,6 @@ mod tests {
(2, 8) (2, 8)
))]), ))]),
(0, 10) (0, 10)
),
(0, 10)
)) ))
])) ]))
) )
@ -1806,8 +1764,7 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::ExpressionNullified(Node::new( Statement::Expression(Expression::block(
Expression::block(
BlockExpression::Sync(vec![ BlockExpression::Sync(vec![
Statement::ExpressionNullified(Node::new( Statement::ExpressionNullified(Node::new(
Expression::assignment( Expression::assignment(
@ -1832,8 +1789,6 @@ mod tests {
)) ))
]), ]),
(0, 34) (0, 34)
),
(0, 34)
)) ))
])) ]))
) )

View File

@ -17,7 +17,7 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::Identifier; use crate::{Enum, Identifier, Struct, Value};
/// Description of a kind of value. /// Description of a kind of value.
/// ///
@ -53,7 +53,7 @@ pub enum Type {
}, },
String, String,
Struct(StructType), Struct(StructType),
Tuple(TupleType), Tuple(Vec<Type>),
} }
impl Type { impl Type {
@ -266,36 +266,8 @@ impl Display for Type {
Type::Number => write!(f, "num"), Type::Number => write!(f, "num"),
Type::Range { r#type } => write!(f, "{type} range"), Type::Range { r#type } => write!(f, "{type} range"),
Type::String => write!(f, "str"), Type::String => write!(f, "str"),
Type::Struct(struct_type) => match struct_type { Type::Struct(struct_type) => write!(f, "{struct_type}"),
StructType::Unit => write!(f, "()"), Type::Tuple(fields) => {
StructType::Tuple(TupleType { 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(FieldsStructType { fields }) => {
write!(f, "{{")?;
for (index, (name, r#type)) in fields.iter().enumerate() {
write!(f, "{name}: {type}")?;
if index != fields.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "}}")
}
},
Type::Tuple(TupleType { fields }) => {
write!(f, "(")?; write!(f, "(")?;
for (index, r#type) in fields.iter().enumerate() { for (index, r#type) in fields.iter().enumerate() {
@ -439,88 +411,257 @@ impl Display for FunctionType {
} }
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum StructType { pub enum StructType {
Unit, Unit {
Tuple(TupleType), name: Identifier,
Fields(FieldsStructType), },
Tuple {
name: Identifier,
fields: Vec<Type>,
},
Fields {
name: Identifier,
fields: HashMap<Identifier, Type>,
},
}
impl StructType {
pub fn name(&self) -> &Identifier {
match self {
StructType::Unit { name } => name,
StructType::Tuple { name, .. } => name,
StructType::Fields { name, .. } => name,
}
}
pub fn constructor(&self) -> Option<Constructor> {
let constructor = match self {
StructType::Unit { name } => Constructor::Unit { name: name.clone() },
StructType::Tuple { name, fields } => Constructor::Tuple(TupleConstructor {
name: name.clone(),
tuple_arguments: Vec::with_capacity(fields.len()),
}),
StructType::Fields { name, fields } => Constructor::Fields {
name: name.clone(),
field_arguments: HashMap::with_capacity(fields.len()),
},
};
Some(constructor)
}
} }
impl Display for StructType { impl Display for StructType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self { match self {
StructType::Unit => write!(f, "()"), StructType::Unit { name } => write!(f, "{name}"),
StructType::Tuple(tuple) => write!(f, "{tuple}"), StructType::Tuple { name, fields } => {
StructType::Fields(fields) => write!(f, "{fields}"), write!(f, "{name}(")?;
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] for (index, field) in fields.iter().enumerate() {
pub struct TupleType {
pub fields: Vec<Type>,
}
impl Display for TupleType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "(")?;
for (index, field) in self.fields.iter().enumerate() {
write!(f, "{field}")?; write!(f, "{field}")?;
if index != self.fields.len() - 1 { if index != fields.len() - 1 {
write!(f, ", ")?; write!(f, ", ")?;
} }
} }
write!(f, ")") write!(f, ")")
} }
} StructType::Fields { name, fields } => {
write!(f, "{name} {{")?;
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] for (index, (identifier, r#type)) in fields.iter().enumerate() {
pub struct FieldsStructType {
pub fields: HashMap<Identifier, Type>,
}
impl Display for FieldsStructType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{{ ")?;
for (index, (identifier, r#type)) in self.fields.iter().enumerate() {
write!(f, "{identifier}: {type}")?; write!(f, "{identifier}: {type}")?;
if index != self.fields.len() - 1 { if index != fields.len() - 1 {
write!(f, ", ")?; write!(f, ", ")?;
} }
} }
write!(f, " }}") write!(f, "}}")
}
}
} }
} }
impl PartialOrd for FieldsStructType { impl PartialOrd for StructType {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other)) Some(self.cmp(other))
} }
} }
impl Ord for FieldsStructType { impl Ord for StructType {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.fields.iter().cmp(other.fields.iter()) match (self, other) {
(StructType::Unit { name: left_name }, StructType::Unit { name: right_name }) => {
left_name.cmp(right_name)
}
(StructType::Unit { .. }, _) => Ordering::Greater,
(
StructType::Tuple {
name: left_name,
fields: left_fields,
},
StructType::Tuple {
name: right_name,
fields: right_fields,
},
) => {
let name_cmp = left_name.cmp(right_name);
if name_cmp == Ordering::Equal {
left_fields.cmp(right_fields)
} else {
name_cmp
}
}
(StructType::Tuple { .. }, _) => Ordering::Greater,
(
StructType::Fields {
name: left_name,
fields: left_fields,
},
StructType::Fields {
name: right_name,
fields: right_fields,
},
) => {
let name_cmp = left_name.cmp(right_name);
if name_cmp == Ordering::Equal {
let len_cmp = left_fields.len().cmp(&right_fields.len());
if len_cmp == Ordering::Equal {
left_fields.iter().cmp(right_fields.iter())
} else {
len_cmp
}
} else {
name_cmp
}
}
(StructType::Fields { .. }, _) => Ordering::Greater,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Constructor {
Unit {
name: Identifier,
},
Tuple(TupleConstructor),
Fields {
name: Identifier,
field_arguments: HashMap<Identifier, Value>,
},
Enum {
name: Identifier,
r#type: EnumType,
variant_constructor: Box<Constructor>,
},
}
impl Constructor {
pub fn construct(self) -> Value {
match self {
Constructor::Unit { name } => Value::Struct(Struct::Unit { name }),
Constructor::Tuple(tuple_constructor) => tuple_constructor.construct(),
Constructor::Fields {
name,
field_arguments,
} => Value::Struct(Struct::Fields {
name,
fields: field_arguments,
}),
Constructor::Enum {
name,
r#type,
variant_constructor,
} => Value::Enum(Enum {
name,
r#type,
variant_data: Self::make_struct(*variant_constructor),
}),
}
}
fn make_struct(this: Self) -> Struct {
match this {
Constructor::Unit { name } => Struct::Unit { name },
Constructor::Tuple(TupleConstructor {
name,
tuple_arguments,
}) => Struct::Tuple {
name,
fields: tuple_arguments,
},
Constructor::Fields {
name,
field_arguments,
} => Struct::Fields {
name,
fields: field_arguments,
},
Constructor::Enum {
variant_constructor,
..
} => Self::make_struct(*variant_constructor),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TupleConstructor {
pub name: Identifier,
pub tuple_arguments: Vec<Value>,
}
impl TupleConstructor {
pub fn push_argument(&mut self, value: Value) {
self.tuple_arguments.push(value);
}
pub fn construct(self) -> Value {
Value::Struct(Struct::Tuple {
name: self.name,
fields: self.tuple_arguments,
})
} }
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EnumType { pub struct EnumType {
name: Identifier, pub name: Identifier,
variants: Vec<StructType>, pub variants: Vec<StructType>,
}
impl EnumType {
pub fn constructor(&self) -> Option<Constructor> {
let get_variant_constructor = self
.variants
.iter()
.find_map(|struct_type| struct_type.constructor());
if let Some(variant_constructor) = get_variant_constructor {
Some(Constructor::Enum {
name: self.name.clone(),
r#type: self.clone(),
variant_constructor: Box::new(variant_constructor),
})
} else {
None
}
}
} }
impl Display for EnumType { impl Display for EnumType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let EnumType { name, variants } = self; let EnumType { name, variants } = self;
write!(f, "enum {name} {{")?; write!(f, "enum {name} {{ ")?;
for (index, variant) in variants.iter().enumerate() { for (index, variant) in variants.iter().enumerate() {
write!(f, "{variant}")?; write!(f, "{variant}")?;
@ -530,7 +671,7 @@ impl Display for EnumType {
} }
} }
write!(f, "}}") write!(f, " }}")
} }
} }

View File

@ -16,8 +16,8 @@ use serde::{
}; };
use crate::{ use crate::{
AbstractSyntaxTree, Context, EnumType, FieldsStructType, FunctionType, Identifier, AbstractSyntaxTree, Context, EnumType, FunctionType, Identifier, RangeableType, RuntimeError,
RangeableType, RuntimeError, StructType, TupleType, Type, Vm, StructType, Type, Vm,
}; };
/// Dust value representation /// Dust value representation
@ -57,7 +57,7 @@ pub enum Value {
Boolean(bool), Boolean(bool),
Byte(u8), Byte(u8),
Character(char), Character(char),
Enum { name: Identifier, r#type: EnumType }, Enum(Enum),
Float(f64), Float(f64),
Function(Function), Function(Function),
Integer(i64), Integer(i64),
@ -80,6 +80,10 @@ impl Value {
Value::Mutable(Arc::new(RwLock::new(value))) Value::Mutable(Arc::new(RwLock::new(value)))
} }
pub fn mutable_from<T: Into<Value>>(into_value: T) -> Value {
Value::Mutable(Arc::new(RwLock::new(into_value.into())))
}
pub fn byte_range(start: u8, end: u8) -> Value { pub fn byte_range(start: u8, end: u8) -> Value {
Value::Range(Rangeable::Byte(start)..Rangeable::Byte(end)) Value::Range(Rangeable::Byte(start)..Rangeable::Byte(end))
} }
@ -188,7 +192,7 @@ impl Value {
Value::Boolean(_) => Type::Boolean, Value::Boolean(_) => Type::Boolean,
Value::Byte(_) => Type::Byte, Value::Byte(_) => Type::Byte,
Value::Character(_) => Type::Character, Value::Character(_) => Type::Character,
Value::Enum { r#type, .. } => Type::Enum(r#type.clone()), Value::Enum(Enum { r#type, .. }) => Type::Enum(r#type.clone()),
Value::Float(_) => Type::Float, Value::Float(_) => Type::Float,
Value::Function(function) => Type::Function(function.r#type.clone()), Value::Function(function) => Type::Function(function.r#type.clone()),
Value::Integer(_) => Type::Integer, Value::Integer(_) => Type::Integer,
@ -221,25 +225,31 @@ impl Value {
} }
Value::String(_) => Type::String, Value::String(_) => Type::String,
Value::Struct(r#struct) => match r#struct { Value::Struct(r#struct) => match r#struct {
Struct::Unit { .. } => Type::Struct(StructType::Unit), Struct::Unit { name } => Type::Struct(StructType::Unit { name: name.clone() }),
Struct::Tuple { fields, .. } => { Struct::Tuple { name, fields } => {
let types = fields.iter().map(|field| field.r#type()).collect(); let types = fields.iter().map(|field| field.r#type()).collect();
Type::Struct(StructType::Tuple(TupleType { fields: types })) Type::Struct(StructType::Tuple {
name: name.clone(),
fields: types,
})
} }
Struct::Fields { fields, .. } => { Struct::Fields { name, fields } => {
let types = fields let types = fields
.iter() .iter()
.map(|(identifier, value)| (identifier.clone(), value.r#type())) .map(|(identifier, value)| (identifier.clone(), value.r#type()))
.collect(); .collect();
Type::Struct(StructType::Fields(FieldsStructType { fields: types })) Type::Struct(StructType::Fields {
name: name.clone(),
fields: types,
})
} }
}, },
Value::Tuple(values) => { Value::Tuple(values) => {
let fields = values.iter().map(|value| value.r#type()).collect(); let fields = values.iter().map(|value| value.r#type()).collect();
Type::Tuple(TupleType { fields }) Type::Tuple(fields)
} }
} }
} }
@ -248,6 +258,7 @@ impl Value {
match self { match self {
Value::Mutable(inner) => inner.read().unwrap().get_field(field), Value::Mutable(inner) => inner.read().unwrap().get_field(field),
Value::Struct(Struct::Fields { fields, .. }) => fields.get(field).cloned(), Value::Struct(Struct::Fields { fields, .. }) => fields.get(field).cloned(),
Value::Map(pairs) => pairs.get(field).cloned(),
_ => None, _ => None,
} }
} }
@ -762,6 +773,54 @@ impl Value {
} }
} }
impl From<bool> for Value {
fn from(value: bool) -> Self {
Value::Boolean(value)
}
}
impl From<u8> for Value {
fn from(value: u8) -> Self {
Value::Byte(value)
}
}
impl From<char> for Value {
fn from(value: char) -> Self {
Value::Character(value)
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Value::Float(value)
}
}
impl From<i32> for Value {
fn from(value: i32) -> Self {
Value::Integer(value as i64)
}
}
impl From<i64> for Value {
fn from(value: i64) -> Self {
Value::Integer(value)
}
}
impl From<String> for Value {
fn from(value: String) -> Self {
Value::String(value)
}
}
impl From<&str> for Value {
fn from(value: &str) -> Self {
Value::String(value.to_string())
}
}
impl Display for Value { impl Display for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
@ -773,7 +832,7 @@ impl Display for Value {
Value::Boolean(boolean) => write!(f, "{boolean}"), Value::Boolean(boolean) => write!(f, "{boolean}"),
Value::Byte(byte) => write!(f, "{byte}"), Value::Byte(byte) => write!(f, "{byte}"),
Value::Character(character) => write!(f, "{character}"), Value::Character(character) => write!(f, "{character}"),
Value::Enum { name, r#type } => write!(f, "{name}::{type}"), Value::Enum(r#enum) => write!(f, "{enum}"),
Value::Float(float) => write!(f, "{float}"), Value::Float(float) => write!(f, "{float}"),
Value::Function(function) => write!(f, "{function}"), Value::Function(function) => write!(f, "{function}"),
Value::Integer(integer) => write!(f, "{integer}"), Value::Integer(integer) => write!(f, "{integer}"),
@ -813,7 +872,7 @@ impl Display for Value {
write!(f, "{start}..={end}") write!(f, "{start}..={end}")
} }
Value::String(string) => write!(f, "{string}"), Value::String(string) => write!(f, "{string}"),
Value::Struct(structure) => write!(f, "{structure}"), Value::Struct(r#struct) => write!(f, "{struct}"),
Value::Tuple(fields) => { Value::Tuple(fields) => {
write!(f, "(")?; write!(f, "(")?;
@ -934,14 +993,7 @@ impl Serialize for Value {
Value::Boolean(boolean) => serializer.serialize_bool(*boolean), Value::Boolean(boolean) => serializer.serialize_bool(*boolean),
Value::Byte(byte) => serializer.serialize_u8(*byte), Value::Byte(byte) => serializer.serialize_u8(*byte),
Value::Character(character) => serializer.serialize_char(*character), Value::Character(character) => serializer.serialize_char(*character),
Value::Enum { name, r#type } => { Value::Enum(r#emum) => r#emum.serialize(serializer),
let mut ser = serializer.serialize_struct_variant("Value", 4, "Enum", 2)?;
ser.serialize_field("name", name)?;
ser.serialize_field("type", r#type)?;
ser.end()
}
Value::Float(float) => serializer.serialize_f64(*float), Value::Float(float) => serializer.serialize_f64(*float),
Value::Function(function) => function.serialize(serializer), Value::Function(function) => function.serialize(serializer),
Value::Integer(integer) => serializer.serialize_i64(*integer), Value::Integer(integer) => serializer.serialize_i64(*integer),
@ -1021,13 +1073,13 @@ impl Function {
value_arguments: Option<Vec<Value>>, value_arguments: Option<Vec<Value>>,
context: &Context, context: &Context,
) -> Result<Option<Value>, RuntimeError> { ) -> Result<Option<Value>, RuntimeError> {
let new_context = Context::with_variables_from(context); let new_context = Context::with_data_from(context);
if let (Some(value_parameters), Some(value_arguments)) = if let (Some(value_parameters), Some(value_arguments)) =
(&self.r#type.value_parameters, value_arguments) (&self.r#type.value_parameters, value_arguments)
{ {
for ((identifier, _), value) in value_parameters.iter().zip(value_arguments) { for ((identifier, _), value) in value_parameters.iter().zip(value_arguments) {
new_context.set_value(identifier.clone(), value); new_context.set_variable_value(identifier.clone(), value);
} }
} }
@ -1226,9 +1278,9 @@ impl Ord for Struct {
impl Display for Struct { impl Display for Struct {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Struct::Unit { .. } => write!(f, "()"), Struct::Unit { name } => write!(f, "{name}"),
Struct::Tuple { fields, .. } => { Struct::Tuple { name, fields } => {
write!(f, "(")?; write!(f, "{name}(")?;
for (index, field) in fields.iter().enumerate() { for (index, field) in fields.iter().enumerate() {
if index > 0 { if index > 0 {
@ -1240,8 +1292,8 @@ impl Display for Struct {
write!(f, ")") write!(f, ")")
} }
Struct::Fields { fields, .. } => { Struct::Fields { name, fields } => {
write!(f, "{{ ")?; write!(f, "{name} {{ ")?;
for (index, (identifier, value)) in fields.iter().enumerate() { for (index, (identifier, value)) in fields.iter().enumerate() {
if index > 0 { if index > 0 {
@ -1310,6 +1362,57 @@ impl Ord for Rangeable {
} }
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Enum {
pub r#type: EnumType,
pub name: Identifier,
pub variant_data: Struct,
}
impl Display for Enum {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let Enum {
name, variant_data, ..
} = self;
match &variant_data {
Struct::Unit { name: variant_name } => write!(f, "{name}::{variant_name}"),
Struct::Tuple {
name: variant_name,
fields,
} => {
write!(f, "{name}::{variant_name}(")?;
for (index, field) in fields.iter().enumerate() {
if index > 0 {
write!(f, ", ")?;
}
write!(f, "{}", field)?;
}
write!(f, ")")
}
Struct::Fields {
name: variant_name,
fields,
} => {
write!(f, "{name}::{variant_name} {{ ")?;
for (index, (identifier, value)) in fields.iter().enumerate() {
if index > 0 {
write!(f, ", ")?;
}
write!(f, "{}: {}", identifier, value)?;
}
write!(f, " }}")
}
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ValueError { pub enum ValueError {
CannotAdd(Value, Value), CannotAdd(Value, Value),

View File

@ -21,8 +21,9 @@ use crate::{
OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span, OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span,
Statement, StructDefinition, StructExpression, Statement, StructDefinition, StructExpression,
}, },
parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, FieldsStructType, parse, Analyzer, BuiltInFunctionError, Constructor, Context, DustError, Enum, EnumType,
Identifier, ParseError, Struct, StructType, TupleType, Type, Value, ValueError, Expression, Identifier, ParseError, Struct, StructType, TupleConstructor, Type, Value,
ValueError,
}; };
/// Run the source code and return the result. /// Run the source code and return the result.
@ -126,11 +127,19 @@ impl Vm {
} }
Statement::StructDefinition(struct_definition) => { Statement::StructDefinition(struct_definition) => {
let (name, struct_type) = match struct_definition.inner { let (name, struct_type) = match struct_definition.inner {
StructDefinition::Unit { name } => (name.inner.clone(), StructType::Unit), StructDefinition::Unit { name } => {
(name.inner.clone(), StructType::Unit { name: name.inner })
}
StructDefinition::Tuple { name, items } => { StructDefinition::Tuple { name, items } => {
let fields = items.into_iter().map(|item| item.inner).collect(); let fields = items.into_iter().map(|item| item.inner).collect();
(name.inner.clone(), StructType::Tuple(TupleType { fields })) (
name.inner.clone(),
StructType::Tuple {
name: name.inner,
fields,
},
)
} }
StructDefinition::Fields { name, fields } => { StructDefinition::Fields { name, fields } => {
let fields = fields let fields = fields
@ -140,23 +149,25 @@ impl Vm {
( (
name.inner.clone(), name.inner.clone(),
StructType::Fields(FieldsStructType { fields }), StructType::Fields {
name: name.inner,
fields,
},
) )
} }
}; };
self.context todo!("Set constructor");
.set_type(name, Type::Struct(struct_type), struct_definition.position);
Ok(None) Ok(None)
} }
}; };
if collect_garbage { if collect_garbage {
self.context.collect_garbage(position); // self.context.collect_garbage(position);
} }
result.map_err(|error| RuntimeError::Trace { result.map_err(|error| RuntimeError::Statement {
error: Box::new(error), error: Box::new(error),
position, position,
}) })
@ -174,7 +185,7 @@ impl Vm {
.run_expression(value, collect_garbage)? .run_expression(value, collect_garbage)?
.expect_value(value_position)?; .expect_value(value_position)?;
self.context.set_value(identifier.inner, value); self.context.set_variable_value(identifier.inner, value);
Ok(()) Ok(())
} }
@ -185,7 +196,8 @@ impl Vm {
.expect_value(value_position)? .expect_value(value_position)?
.into_mutable(); .into_mutable();
self.context.set_value(identifier.inner, mutable_value); self.context
.set_variable_value(identifier.inner, mutable_value);
Ok(()) Ok(())
} }
@ -210,7 +222,7 @@ impl Vm {
self.run_expression(*expression.inner, collect_garbage) self.run_expression(*expression.inner, collect_garbage)
} }
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let get_value = self.context.get_value(&identifier.inner); let get_value = self.context.get_variable_value(&identifier.inner);
if let Some(value) = get_value { if let Some(value) = get_value {
Ok(Evaluation::Return(Some(value))) Ok(Evaluation::Return(Some(value)))
@ -243,7 +255,7 @@ impl Vm {
Expression::TupleAccess(_) => todo!(), Expression::TupleAccess(_) => todo!(),
}; };
evaluation_result.map_err(|error| RuntimeError::Trace { evaluation_result.map_err(|error| RuntimeError::Expression {
error: Box::new(error), error: Box::new(error),
position, position,
}) })
@ -257,20 +269,20 @@ impl Vm {
match struct_expression { match struct_expression {
StructExpression::Unit { name } => { StructExpression::Unit { name } => {
let position = name.position; let position = name.position;
let r#type = self.context.get_type(&name.inner).ok_or_else(|| { let r#type = self.context.get_variable_type(&name.inner).ok_or_else(|| {
RuntimeError::UndefinedType { RuntimeError::UndefinedType {
identifier: name.inner.clone(), identifier: name.inner.clone(),
position, position,
} }
})?; })?;
if let Type::Struct(StructType::Unit) = r#type { if let Type::Struct(StructType::Unit { name }) = r#type {
Ok(Evaluation::Return(Some(Value::Struct(Struct::Unit { Ok(Evaluation::Return(Some(Value::Struct(Struct::Unit {
name: name.inner, name,
})))) }))))
} else { } else {
Err(RuntimeError::ExpectedType { Err(RuntimeError::ExpectedType {
expected: Type::Struct(StructType::Unit), expected: Type::Struct(StructType::Unit { name: name.inner }),
actual: r#type, actual: r#type,
position, position,
}) })
@ -281,14 +293,14 @@ impl Vm {
fields: expressions, fields: expressions,
} => { } => {
let position = name.position; let position = name.position;
let r#type = self.context.get_type(&name.inner).ok_or_else(|| { let r#type = self.context.get_variable_type(&name.inner).ok_or_else(|| {
RuntimeError::UndefinedType { RuntimeError::UndefinedType {
identifier: name.inner.clone(), identifier: name.inner.clone(),
position, position,
} }
})?; })?;
if let Type::Struct(StructType::Fields(FieldsStructType { .. })) = r#type { if let Type::Struct(StructType::Fields { name, .. }) = r#type {
let mut values = HashMap::with_capacity(expressions.len()); let mut values = HashMap::with_capacity(expressions.len());
for (identifier, expression) in expressions { for (identifier, expression) in expressions {
@ -301,14 +313,15 @@ impl Vm {
} }
Ok(Evaluation::Return(Some(Value::Struct(Struct::Fields { Ok(Evaluation::Return(Some(Value::Struct(Struct::Fields {
name: name.inner, name,
fields: values, fields: values,
})))) }))))
} else { } else {
Err(RuntimeError::ExpectedType { Err(RuntimeError::ExpectedType {
expected: Type::Struct(StructType::Fields(FieldsStructType { expected: Type::Struct(StructType::Fields {
fields: HashMap::new(), name: name.inner,
})), fields: Default::default(),
}),
actual: r#type, actual: r#type,
position, position,
}) })
@ -609,11 +622,7 @@ impl Vm {
Ok(Evaluation::Return(None)) Ok(Evaluation::Return(None))
} }
LoopExpression::For { LoopExpression::For { .. } => todo!(),
identifier,
iterator,
block,
} => todo!(),
} }
} }
@ -668,8 +677,47 @@ impl Vm {
let CallExpression { invoker, arguments } = call_expression; let CallExpression { invoker, arguments } = call_expression;
let invoker_position = invoker.position(); let invoker_position = invoker.position();
let invoker_value = let run_invoker = self.run_expression(invoker, collect_garbage)?;
if let Some(value) = self.run_expression(invoker, collect_garbage)?.value() {
if let Evaluation::Constructor(Type::Struct(StructType::Tuple { name, fields })) =
&run_invoker
{
let struct_type = fields
.iter()
.find(|r#type| {
if let Type::Struct(struct_type) = r#type {
struct_type.name() == name
} else {
false
}
})
.ok_or(RuntimeError::EnumVariantNotFound {
identifier: name.clone(),
position: invoker_position,
})?;
if let Type::Struct(StructType::Tuple { name, fields }) = struct_type {
let mut values = Vec::with_capacity(arguments.len());
for argument in arguments {
let position = argument.position();
let value = self
.run_expression(argument, collect_garbage)?
.expect_value(position)?;
values.push(value);
}
let r#struct = Struct::Tuple {
name: name.clone(),
fields: values,
};
return Ok(Evaluation::Return(Some(Value::Struct(r#struct))));
}
}
let invoker_value = if let Some(value) = run_invoker.value() {
value value
} else { } else {
return Err(RuntimeError::ExpectedValue { return Err(RuntimeError::ExpectedValue {
@ -814,7 +862,7 @@ impl Vm {
previous_value = self.run_statement(statement, collect_garbage)?; previous_value = self.run_statement(statement, collect_garbage)?;
if collect_garbage { if collect_garbage {
self.context.collect_garbage(position); // self.context.collect_garbage(position);
} }
} }
@ -864,7 +912,7 @@ impl Vm {
match r#else { match r#else {
ElseExpression::If(if_expression) => { ElseExpression::If(if_expression) => {
self.run_expression(Expression::If(if_expression), collect_garbage) self.run_if(*if_expression.inner, collect_garbage)
} }
ElseExpression::Block(block) => self.run_block(block.inner, collect_garbage), ElseExpression::Block(block) => self.run_block(block.inner, collect_garbage),
} }
@ -875,14 +923,15 @@ impl Vm {
enum Evaluation { enum Evaluation {
Break, Break,
Constructor(Type),
Return(Option<Value>), Return(Option<Value>),
} }
impl Evaluation { impl Evaluation {
pub fn value(self) -> Option<Value> { pub fn value(self) -> Option<Value> {
match self { match self {
Evaluation::Break => None,
Evaluation::Return(value_option) => value_option, Evaluation::Return(value_option) => value_option,
_ => None,
} }
} }
@ -898,7 +947,11 @@ impl Evaluation {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum RuntimeError { pub enum RuntimeError {
ParseError(ParseError), ParseError(ParseError),
Trace { Expression {
error: Box<RuntimeError>,
position: Span,
},
Statement {
error: Box<RuntimeError>, error: Box<RuntimeError>,
position: Span, position: Span,
}, },
@ -914,9 +967,17 @@ pub enum RuntimeError {
error: BuiltInFunctionError, error: BuiltInFunctionError,
position: Span, position: Span,
}, },
EnumVariantNotFound {
identifier: Identifier,
position: Span,
},
ExpectedBoolean { ExpectedBoolean {
position: Span, position: Span,
}, },
ExpectedConstructor {
actual: Type,
position: Span,
},
ExpectedIdentifier { ExpectedIdentifier {
position: Span, position: Span,
}, },
@ -974,14 +1035,17 @@ impl RuntimeError {
pub fn position(&self) -> Span { pub fn position(&self) -> Span {
match self { match self {
Self::ParseError(parse_error) => parse_error.position(), Self::ParseError(parse_error) => parse_error.position(),
Self::Trace { position, .. } => *position, Self::Expression { position, .. } => *position,
Self::Statement { position, .. } => *position,
Self::ValueError { Self::ValueError {
left_position, left_position,
right_position, right_position,
.. ..
} => (left_position.0, right_position.1), } => (left_position.0, right_position.1),
Self::BuiltInFunctionError { position, .. } => *position, Self::BuiltInFunctionError { position, .. } => *position,
Self::EnumVariantNotFound { position, .. } => *position,
Self::ExpectedBoolean { position } => *position, Self::ExpectedBoolean { position } => *position,
Self::ExpectedConstructor { position, .. } => *position,
Self::ExpectedFunction { position, .. } => *position, Self::ExpectedFunction { position, .. } => *position,
Self::ExpectedIdentifier { position } => *position, Self::ExpectedIdentifier { position } => *position,
Self::ExpectedIdentifierOrString { position } => *position, Self::ExpectedIdentifierOrString { position } => *position,
@ -1016,10 +1080,17 @@ impl Display for RuntimeError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Self::ParseError(parse_error) => write!(f, "{}", parse_error), Self::ParseError(parse_error) => write!(f, "{}", parse_error),
Self::Trace { error, position } => { Self::Expression { error, position } => {
write!( write!(
f, f,
"Error during execution at position: {:?}\n{}", "Error while running expression at {:?}: {}",
position, error
)
}
Self::Statement { error, position } => {
write!(
f,
"Error while running statement at {:?}: {}",
position, error position, error
) )
} }
@ -1037,9 +1108,26 @@ impl Display for RuntimeError {
Self::BuiltInFunctionError { error, .. } => { Self::BuiltInFunctionError { error, .. } => {
write!(f, "{}", error) write!(f, "{}", error)
} }
Self::EnumVariantNotFound {
identifier,
position,
} => {
write!(
f,
"Enum variant not found: {} at position: {:?}",
identifier, position
)
}
Self::ExpectedBoolean { position } => { Self::ExpectedBoolean { position } => {
write!(f, "Expected a boolean at position: {:?}", position) write!(f, "Expected a boolean at position: {:?}", position)
} }
Self::ExpectedConstructor { actual, position } => {
write!(
f,
"Expected a constructor, but got {} at position: {:?}",
actual, position
)
}
Self::ExpectedFunction { actual, position } => { Self::ExpectedFunction { actual, position } => {
write!( write!(
f, f,
@ -1110,7 +1198,7 @@ impl Display for RuntimeError {
} => { } => {
write!( write!(
f, f,
"Undefined variable {} at position: {:?}", "Undefined value {} at position: {:?}",
identifier, position identifier, position
) )
} }
@ -1187,8 +1275,8 @@ mod tests {
#[test] #[test]
fn assign_tuple_struct_variable() { fn assign_tuple_struct_variable() {
let input = " let input = "
struct Foo(int) struct Foo(int);
x = Foo(42) let x = Foo(42);
x x
"; ";
@ -1203,7 +1291,7 @@ mod tests {
#[test] #[test]
fn define_and_instantiate_tuple_struct() { fn define_and_instantiate_tuple_struct() {
let input = "struct Foo(int) Foo(42)"; let input = "struct Foo(int); Foo(42)";
assert_eq!( assert_eq!(
run(input), run(input),
@ -1232,7 +1320,7 @@ mod tests {
#[test] #[test]
fn define_and_instantiate_unit_struct() { fn define_and_instantiate_unit_struct() {
let input = "struct Foo Foo"; let input = "struct Foo; Foo";
assert_eq!( assert_eq!(
run(input), run(input),
@ -1271,6 +1359,8 @@ mod tests {
#[test] #[test]
fn negate_expression() { fn negate_expression() {
env_logger::builder().is_test(true).try_init().unwrap();
let input = "let x = -42; -x"; let input = "let x = -42; -x";
assert_eq!(run(input), Ok(Some(Value::Integer(42)))); assert_eq!(run(input), Ok(Some(Value::Integer(42))));
@ -1292,7 +1382,7 @@ mod tests {
#[test] #[test]
fn map_property_access() { fn map_property_access() {
let input = "{ a = 42 }.a"; let input = "map { a = 42 }.a";
assert_eq!(run(input), Ok(Some(Value::Integer(42)))); assert_eq!(run(input), Ok(Some(Value::Integer(42))));
} }
@ -1343,21 +1433,21 @@ mod tests {
fn while_loop() { fn while_loop() {
let input = "let mut x = 0; while x < 5 { x += 1 } x"; let input = "let mut x = 0; while x < 5 { x += 1 } x";
assert_eq!(run(input), Ok(Some(Value::Integer(5)))); assert_eq!(run(input), Ok(Some(Value::mutable_from(5))));
} }
#[test] #[test]
fn subtract_assign() { fn subtract_assign() {
let input = "let mut x = 1; x -= 1; x"; let input = "let mut x = 1; x -= 1; x";
assert_eq!(run(input), Ok(Some(Value::mutable(Value::Integer(0))))); assert_eq!(run(input), Ok(Some(Value::mutable_from(0))));
} }
#[test] #[test]
fn add_assign() { fn add_assign() {
let input = "let mut x = 1; x += 1; x"; let input = "let mut x = 1; x += 1; x";
assert_eq!(run(input), Ok(Some(Value::mutable(Value::Integer(2))))); assert_eq!(run(input), Ok(Some(Value::mutable_from(2))));
} }
#[test] #[test]

View File

@ -10,3 +10,4 @@ repository.workspace = true
[dependencies] [dependencies]
clap = { version = "4.5.14", features = ["derive"] } clap = { version = "4.5.14", features = ["derive"] }
dust-lang = { path = "../dust-lang" } dust-lang = { path = "../dust-lang" }
env_logger = "0.11.5"

View File

@ -8,21 +8,39 @@ struct Cli {
#[arg(short, long)] #[arg(short, long)]
command: Option<String>, command: Option<String>,
#[arg(short, long)]
parse: bool,
path: Option<String>, path: Option<String>,
} }
fn main() { fn main() {
env_logger::init();
let args = Cli::parse(); let args = Cli::parse();
if let Some(command) = &args.command { if let Some(command) = &args.command {
if args.parse {
parse_and_display_errors(command);
} else {
run_and_display_errors(command); run_and_display_errors(command);
}
} else if let Some(path) = &args.path { } else if let Some(path) = &args.path {
let source = read_to_string(path).expect("Failed to read file"); let source = read_to_string(path).expect("Failed to read file");
run_and_display_errors(&source) if args.parse {
parse_and_display_errors(&source);
} else { } else {
panic!("No command or path provided"); run_and_display_errors(&source);
}; }
}
}
fn parse_and_display_errors(source: &str) {
match dust_lang::parse(source) {
Ok(ast) => println!("{:#?}", ast),
Err(error) => eprintln!("{}", error.report()),
}
} }
fn run_and_display_errors(source: &str) { fn run_and_display_errors(source: &str) {