diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index a183b66..3eddb32 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -1,5 +1,7 @@ use std::{cmp::Ordering, collections::BTreeMap, ops::Range}; +use chumsky::container::Container; + use crate::{ context::Context, error::{RuntimeError, ValidationError}, @@ -165,7 +167,27 @@ impl AbstractTree for ValueNode { return_type, body, } => Value::function(parameters, return_type, body), - ValueNode::Structure { name, fields } => todo!(), + ValueNode::Structure { + name, + fields: expressions, + } => { + let mut fields = Vec::with_capacity(expressions.len()); + + for (identifier, expression) in expressions { + let action = expression.node.run(_context)?; + let value = if let Action::Return(value) = action { + value + } else { + return Err(RuntimeError::ValidationFailure( + ValidationError::InterpreterExpectedReturn(expression.position), + )); + }; + + fields.push((identifier, value)); + } + + Value::structure(name, fields) + } }; Ok(Action::Return(value)) diff --git a/src/value.rs b/src/value.rs index 2eef0be..f7df626 100644 --- a/src/value.rs +++ b/src/value.rs @@ -70,6 +70,10 @@ impl Value { )))) } + pub fn structure(name: Identifier, fields: Vec<(Identifier, Value)>) -> Self { + Value(Arc::new(ValueInner::Structure { name, fields })) + } + pub fn built_in_function(function: BuiltInFunction) -> Self { Value(Arc::new(ValueInner::Function(Function::BuiltIn(function)))) } @@ -108,13 +112,11 @@ impl Value { } => { let mut fields = Vec::with_capacity(expressions.len()); - for (identifier, expression) in expressions { - let r#type = expression - .node - .expected_type(context)? - .with_position(expression.position); - - fields.push((identifier.clone(), r#type)); + for (identifier, value) in expressions { + fields.push(( + identifier.clone(), + value.r#type(context)?.with_position((0, 0)), + )); } Type::Structure { @@ -229,7 +231,7 @@ pub enum ValueInner { String(String), Structure { name: Identifier, - fields: Vec<(Identifier, WithPosition)>, + fields: Vec<(Identifier, Value)>, }, } diff --git a/tests/structs.rs b/tests/structs.rs new file mode 100644 index 0000000..c466006 --- /dev/null +++ b/tests/structs.rs @@ -0,0 +1,27 @@ +use dust_lang::{abstract_tree::Identifier, *}; + +#[test] +fn simple_structure() { + assert_eq!( + interpret( + " + struct Foo { + bar : int, + baz : str, + } + + Foo { + bar = 42, + baz = 'hiya', + } + " + ), + Ok(Some(Value::structure( + Identifier::new("Foo"), + vec![ + (Identifier::new("bar"), Value::integer(42)), + (Identifier::new("baz"), Value::string("hiya".to_string())), + ] + ))) + ) +}