diff --git a/dust-lang/src/ast/statement.rs b/dust-lang/src/ast/statement.rs index 6fc6aef..97993cc 100644 --- a/dust-lang/src/ast/statement.rs +++ b/dust-lang/src/ast/statement.rs @@ -31,7 +31,7 @@ impl Statement { pub fn return_type(&self, context: &Context) -> Option { match self { Statement::Expression(expression) => expression.return_type(context), - Statement::ExpressionNullified(expression) => None, + Statement::ExpressionNullified(_) => None, Statement::Let(_) => None, Statement::StructDefinition(_) => None, } @@ -42,9 +42,37 @@ impl Display for Statement { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { Statement::Expression(expression) => write!(f, "{}", expression), - Statement::ExpressionNullified(expression) => write!(f, "{}", expression), - Statement::Let(r#let) => write!(f, "{}", r#let), - Statement::StructDefinition(definition) => write!(f, "{}", definition), + Statement::ExpressionNullified(expression) => write!(f, "{};", expression), + Statement::Let(r#let) => write!(f, "{};", r#let), + Statement::StructDefinition(struct_definition) => match &struct_definition.inner { + StructDefinition::Unit { name } => write!(f, "struct {};", name), + StructDefinition::Tuple { name, items } => { + write!(f, "struct {name} {{ ")?; + + for (index, item) in items.iter().enumerate() { + write!(f, "{}: {}", item, index)?; + + if index < items.len() - 1 { + write!(f, ", ")?; + } + } + + write!(f, " }}") + } + StructDefinition::Fields { name, fields } => { + write!(f, "struct {name} {{ ")?; + + for (index, (field, r#type)) in fields.iter().enumerate() { + write!(f, "{}: {}", field, r#type)?; + + if index < fields.len() - 1 { + write!(f, ", ")?; + } + } + + write!(f, " }}") + } + }, } } } diff --git a/dust-lang/src/constructor.rs b/dust-lang/src/constructor.rs index f2320a7..8e2eb91 100644 --- a/dust-lang/src/constructor.rs +++ b/dust-lang/src/constructor.rs @@ -1,4 +1,7 @@ -use std::collections::HashMap; +use std::{ + collections::HashMap, + fmt::{self, Display, Formatter}, +}; use serde::{Deserialize, Serialize}; @@ -11,6 +14,16 @@ pub enum Constructor { Fields(FieldsConstructor), } +impl Display for Constructor { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Constructor::Unit(unit) => write!(f, "{}", unit.name), + Constructor::Tuple(tuple) => write!(f, "{}", tuple.name), + Constructor::Fields(fields) => write!(f, "{}", fields.name), + } + } +} + #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct UnitConstructor { pub name: Identifier, diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index eefbdee..fb4501e 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -108,7 +108,7 @@ impl Context { /// Associates a constructor with an identifier. pub fn set_constructor(&self, identifier: Identifier, constructor: Constructor) { - log::trace!("Setting {identifier} to constructor {constructor:?}"); + log::trace!("Setting {identifier} to constructor {constructor}"); let mut variables = self.variables.write().unwrap(); @@ -130,7 +130,7 @@ impl Context { struct_type: StructType, position: Span, ) { - log::trace!("Setting {identifier} to constructor of type {struct_type:?}"); + log::trace!("Setting {identifier} to constructor of type {struct_type}"); let mut variables = self.variables.write().unwrap(); diff --git a/dust-lang/src/type.rs b/dust-lang/src/type.rs index 7822d45..fe6afbd 100644 --- a/dust-lang/src/type.rs +++ b/dust-lang/src/type.rs @@ -13,14 +13,13 @@ use std::{ cmp::Ordering, collections::HashMap, fmt::{self, Display, Formatter}, - rc::Weak, }; use serde::{Deserialize, Serialize}; use crate::{ constructor::{FieldsConstructor, TupleConstructor, UnitConstructor}, - Constructor, Enum, Identifier, Struct, Value, + Constructor, Identifier, }; /// Description of a kind of value. diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 46837f7..99899e0 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -7,7 +7,6 @@ use std::{ collections::HashMap, fmt::{self, Display, Formatter}, - primitive, sync::{Arc, Mutex}, }; @@ -21,8 +20,8 @@ use crate::{ OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span, Statement, StructDefinition, StructExpression, }, - parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, DustError, Enum, - EnumType, Expression, Identifier, ParseError, Struct, StructType, Type, Value, ValueError, + parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, DustError, + Expression, Identifier, ParseError, Struct, StructType, Type, Value, ValueError, }; /// Run the source code and return the result. @@ -109,6 +108,8 @@ impl Vm { statement: Statement, collect_garbage: bool, ) -> Result, RuntimeError> { + log::debug!("Running statement: {}", statement); + let position = statement.position(); let result = match statement { Statement::Expression(expression) => self @@ -211,6 +212,8 @@ impl Vm { expression: Expression, collect_garbage: bool, ) -> Result { + log::debug!("Running expression: {}", expression); + let position = expression.position(); let evaluation_result = match expression { Expression::Block(Node { inner, .. }) => self.run_block(*inner, collect_garbage), @@ -222,13 +225,19 @@ impl Vm { self.run_expression(*expression.inner, collect_garbage) } Expression::Identifier(identifier) => { + log::debug!("Running identifier: {}", identifier.inner); + let get_data = self.context.get_data(&identifier.inner); if let Some(ContextData::VariableValue(value)) = get_data { - return Ok(Evaluation::Return(Some(value.clone()))); + return Ok(Evaluation::Return(Some(value))); } if let Some(ContextData::Constructor(constructor)) = get_data { + if let Constructor::Unit(unit_constructor) = constructor { + return Ok(Evaluation::Return(Some(unit_constructor.construct()))); + } + return Ok(Evaluation::Constructor(constructor)); } @@ -270,6 +279,8 @@ impl Vm { struct_expression: StructExpression, collect_garbage: bool, ) -> Result { + log::debug!("Running struct expression: {struct_expression}"); + match struct_expression { StructExpression::Unit { name } => { let position = name.position; @@ -678,14 +689,19 @@ impl Vm { call_expression: CallExpression, collect_garbage: bool, ) -> Result { + log::debug!("Running call expression: {call_expression}"); + let CallExpression { invoker, arguments } = call_expression; let invoker_position = invoker.position(); let run_invoker = self.run_expression(invoker, collect_garbage)?; match run_invoker { - Evaluation::Constructor(constructor) => { - if let Constructor::Tuple(tuple_constructor) = constructor { + Evaluation::Constructor(constructor) => match constructor { + Constructor::Unit(unit_constructor) => { + Ok(Evaluation::Return(Some(unit_constructor.construct()))) + } + Constructor::Tuple(tuple_constructor) => { let mut fields = Vec::new(); for argument in arguments { @@ -701,9 +717,12 @@ impl Vm { let tuple = tuple_constructor.construct(fields); - return Ok(Evaluation::Return(Some(tuple))); + Ok(Evaluation::Return(Some(tuple))) } - } + Constructor::Fields(_) => { + todo!("Return an error") + } + }, Evaluation::Return(Some(value)) => { let function = if let Value::Function(function) = value { function @@ -718,26 +737,23 @@ impl Vm { for argument in arguments { let position = argument.position(); + let value = self + .run_expression(argument, collect_garbage)? + .expect_value(position)?; - if let Some(value) = self.run_expression(argument, collect_garbage)?.value() { - value_arguments.push(value); - } else { - return Err(RuntimeError::ExpectedValue { position }); - } + value_arguments.push(value); } let context = Context::new(); - return function + function .call(None, Some(value_arguments), &context) - .map(Evaluation::Return); + .map(Evaluation::Return) } - _ => (), + _ => Err(RuntimeError::ExpectedValueOrConstructor { + position: invoker_position, + }), } - - Err(RuntimeError::ExpectedValue { - position: invoker_position, - }) } fn run_field_access( @@ -998,6 +1014,9 @@ pub enum RuntimeError { ExpectedValue { position: Span, }, + ExpectedValueOrConstructor { + position: Span, + }, InvalidRange { start_position: Span, end_position: Span, @@ -1050,6 +1069,7 @@ impl RuntimeError { } => (start_position.0, end_position.1), Self::UndefinedType { position, .. } => *position, Self::UndefinedValue { position, .. } => *position, + Self::ExpectedValueOrConstructor { position } => *position, Self::UndefinedProperty { property_position, .. } => *property_position, @@ -1169,6 +1189,13 @@ impl Display for RuntimeError { Self::ExpectedValue { position } => { write!(f, "Expected a value at position: {:?}", position) } + Self::ExpectedValueOrConstructor { position } => { + write!( + f, + "Expected a value or constructor at position: {:?}", + position + ) + } Self::InvalidRange { start_position, end_position, @@ -1291,6 +1318,8 @@ mod tests { #[test] fn assign_unit_struct_variable() { + env_logger::builder().is_test(true).try_init().unwrap(); + let input = " struct Foo; let x = Foo;