diff --git a/src/abstract_tree/built_in_value.rs b/src/abstract_tree/built_in_value.rs index 8ee01e8..6f9232e 100644 --- a/src/abstract_tree/built_in_value.rs +++ b/src/abstract_tree/built_in_value.rs @@ -31,12 +31,12 @@ impl BuiltInValue { match self { BuiltInValue::Args => Type::list(Type::String), BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(), - BuiltInValue::Fs => Type::Map, - BuiltInValue::Json => Type::Map, + BuiltInValue::Fs => Type::Map(None), + BuiltInValue::Json => Type::Map(None), BuiltInValue::Length => BuiltInFunction::Length.r#type(), BuiltInValue::Output => BuiltInFunction::Output.r#type(), - BuiltInValue::Random => Type::Map, - BuiltInValue::String => Type::Map, + BuiltInValue::Random => Type::Map(None), + BuiltInValue::String => Type::Map(None), } } diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index 2c19511..32def88 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -92,7 +92,7 @@ impl AbstractTree for Index { fn expected_type(&self, context: &Map) -> Result { match self.collection.expected_type(context)? { Type::List(item_type) => Ok(*item_type.clone()), - Type::Map => Ok(Type::Any), + Type::Map(_) => Ok(Type::Any), Type::None => Ok(Type::None), r#type => Ok(r#type), } diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index dd64b8c..caf662a 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -40,7 +40,7 @@ use tree_sitter::Node; use crate::{Error, Map, Result, Value}; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct SyntaxPosition { pub start_byte: usize, pub end_byte: usize, @@ -63,6 +63,7 @@ impl From for SyntaxPosition { } } +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Root { statements: Vec, } diff --git a/src/abstract_tree/type_definition.rs b/src/abstract_tree/type_definition.rs index 083db30..511ed32 100644 --- a/src/abstract_tree/type_definition.rs +++ b/src/abstract_tree/type_definition.rs @@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Map, Result, Value}; +use crate::{AbstractTree, Error, Map, Result, Structure, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct TypeDefinition { @@ -61,7 +61,7 @@ pub enum Type { }, Integer, List(Box), - Map, + Map(Option), None, Number, String, @@ -92,13 +92,13 @@ impl Type { | (Type::Collection, Type::Collection) | (Type::Collection, Type::List(_)) | (Type::List(_), Type::Collection) - | (Type::Collection, Type::Map) - | (Type::Map, Type::Collection) + | (Type::Collection, Type::Map(_)) + | (Type::Map(_), Type::Collection) | (Type::Collection, Type::String) | (Type::String, Type::Collection) | (Type::Float, Type::Float) | (Type::Integer, Type::Integer) - | (Type::Map, Type::Map) + | (Type::Map(_), Type::Map(_)) | (Type::Number, Type::Number) | (Type::Number, Type::Integer) | (Type::Number, Type::Float) @@ -215,7 +215,7 @@ impl AbstractTree for Type { } } "int" => Type::Integer, - "map" => Type::Map, + "map" => Type::Map(None), "num" => Type::Number, "none" => Type::None, "str" => Type::String, @@ -273,7 +273,7 @@ impl Display for Type { } Type::Integer => write!(f, "int"), Type::List(item_type) => write!(f, "[{item_type}]"), - Type::Map => write!(f, "map"), + Type::Map(_) => write!(f, "map"), Type::Number => write!(f, "num"), Type::None => write!(f, "none"), Type::String => write!(f, "str"), diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index d7ed53f..4766c88 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -5,7 +5,7 @@ use tree_sitter::Node; use crate::{ AbstractTree, BuiltInValue, Error, Expression, Function, Identifier, List, Map, Result, - Statement, Type, TypeDefinition, Value, + Statement, Structure, Type, TypeDefinition, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -116,7 +116,7 @@ impl AbstractTree for ValueNode { let mut current_type: Option = None; let mut current_statement = None; - for index in 0..child.child_count() - 1 { + for index in 2..child.child_count() - 1 { let child_syntax_node = child.child(index).unwrap(); if child_syntax_node.kind() == "identifier" { @@ -151,9 +151,15 @@ impl AbstractTree for ValueNode { context, )?); - if let (Some(identifier), Some(r#type)) = - (¤t_identifier, ¤t_type) - { + if let Some(identifier) = ¤t_identifier { + let r#type = if let Some(r#type) = ¤t_type { + r#type.clone() + } else if let Some(statement) = ¤t_statement { + statement.expected_type(context)? + } else { + Type::None + }; + btree_map.insert( identifier.inner().clone(), (current_statement.clone(), r#type.clone()), @@ -223,16 +229,16 @@ impl AbstractTree for ValueNode { let mut value_map = BTreeMap::new(); for (key, (statement_option, r#type)) in node_map { - let value = if let Some(statement) = statement_option { - statement.run(source, context)? + let value_option = if let Some(statement) = statement_option { + Some(statement.run(source, context)?) } else { - Value::none() + None }; - value_map.insert(key.to_string(), (Some(value), r#type.clone())); + value_map.insert(key.to_string(), (value_option, r#type.clone())); } - Value::Structure(value_map) + Value::Structure(Structure::new(value_map)) } }; @@ -274,9 +280,17 @@ impl AbstractTree for ValueNode { Type::None } } - ValueNode::Map(_) => Type::Map, + ValueNode::Map(_) => Type::Map(None), ValueNode::BuiltInValue(built_in_value) => built_in_value.expected_type(context)?, - ValueNode::Structure(_) => todo!(), + ValueNode::Structure(node_map) => { + let mut value_map = BTreeMap::new(); + + for (key, (_statement_option, r#type)) in node_map { + value_map.insert(key.to_string(), (None, r#type.clone())); + } + + Type::Map(Some(Structure::new(value_map))) + } }; Ok(r#type) diff --git a/src/lib.rs b/src/lib.rs index 92b79fb..e4b3924 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ pub use crate::{ built_in_functions::BuiltInFunction, error::*, interpret::*, - value::{function::Function, list::List, map::Map, Value}, + value::{function::Function, list::List, map::Map, structure::Structure, Value}, }; pub use tree_sitter::Node as SyntaxNode; diff --git a/src/value/map.rs b/src/value/map.rs index 11f69d9..0102fc4 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -11,7 +11,7 @@ use std::{ sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, }; -use crate::{value::Value, Result, Type}; +use crate::{value::Value, Result, Structure, Type}; /// A collection dust variables comprised of key-value pairs. /// @@ -20,6 +20,7 @@ use crate::{value::Value, Result, Type}; #[derive(Clone, Debug)] pub struct Map { variables: Arc>>, + structure: Option, } impl Map { @@ -27,6 +28,7 @@ impl Map { pub fn new() -> Self { Map { variables: Arc::new(RwLock::new(BTreeMap::new())), + structure: None, } } @@ -39,6 +41,7 @@ impl Map { Ok(Map { variables: Arc::new(RwLock::new(new_map)), + structure: other.structure.clone(), }) } diff --git a/src/value/mod.rs b/src/value/mod.rs index 3098689..5db9c85 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,7 +1,7 @@ //! Types that represent runtime values. use crate::{ error::{Error, Result}, - Function, Identifier, List, Map, Type, TypeDefinition, + Function, Identifier, List, Map, Structure, Type, TypeDefinition, }; use serde::{ @@ -12,7 +12,6 @@ use serde::{ use std::{ cmp::Ordering, - collections::BTreeMap, convert::TryFrom, fmt::{self, Display, Formatter}, marker::PhantomData, @@ -23,6 +22,7 @@ use std::{ pub mod function; pub mod list; pub mod map; +pub mod structure; /// Dust value representation. /// @@ -39,7 +39,7 @@ pub enum Value { Integer(i64), Boolean(bool), Option(Option>), - Structure(BTreeMap, Type)>), + Structure(Structure), } impl Default for Value { @@ -86,7 +86,7 @@ impl Value { )); } - Type::Map + Type::Map(None) } Value::Function(function) => function.r#type().clone(), Value::String(_) => Type::String, @@ -541,18 +541,7 @@ impl Display for Value { Value::List(list) => write!(f, "{list}"), Value::Map(map) => write!(f, "{map}"), Value::Function(function) => write!(f, "{function}"), - Value::Structure(btree_map) => { - writeln!(f, "{{")?; - - for (key, (value_option, r#type)) in btree_map { - if let Some(value) = value_option { - writeln!(f, " {key} {} = {value}", r#type)?; - } else { - writeln!(f, " {key} {}", r#type)?; - } - } - write!(f, "}}") - } + Value::Structure(structure) => write!(f, "{structure}"), } } } diff --git a/src/value/structure.rs b/src/value/structure.rs new file mode 100644 index 0000000..f780dbf --- /dev/null +++ b/src/value/structure.rs @@ -0,0 +1,37 @@ +use std::{ + collections::BTreeMap, + fmt::{self, Display, Formatter}, + sync::Arc, +}; + +use serde::{Deserialize, Serialize}; + +use crate::{Type, Value}; + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct Structure(Arc, Type)>>); + +impl Structure { + pub fn new(map: BTreeMap, Type)>) -> Self { + Structure(Arc::new(map)) + } + + pub fn inner(&self) -> &BTreeMap, Type)> { + &self.0 + } +} + +impl Display for Structure { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + writeln!(f, "{{")?; + + for (key, (value_option, r#type)) in self.0.as_ref() { + if let Some(value) = value_option { + writeln!(f, " {key} <{}> = {value}", r#type)?; + } else { + writeln!(f, " {key} <{}>", r#type)?; + } + } + write!(f, "}}") + } +} diff --git a/tests/structure.rs b/tests/structure.rs index c0f5c93..c91094f 100644 --- a/tests/structure.rs +++ b/tests/structure.rs @@ -10,5 +10,5 @@ fn simple_structure() { btree_map.insert("x".to_string(), (Some(Value::Integer(0)), Type::Integer)); - assert_eq!(Ok(Value::Structure(btree_map)), result); + assert_eq!(Ok(Value::Structure(Structure::new(btree_map))), result); }