From c2ba519240143b837a9fb1a999d4c2864353177b Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 15 Feb 2024 15:20:29 -0500 Subject: [PATCH] Overhaul built-ins and identifiers --- src/abstract_tree/assignment.rs | 18 ++-- src/abstract_tree/enum_defintion.rs | 9 +- src/abstract_tree/for.rs | 4 +- src/abstract_tree/function_call.rs | 13 +-- src/abstract_tree/function_node.rs | 2 +- src/abstract_tree/identifier.rs | 79 +++++++++++---- src/abstract_tree/index.rs | 57 +++-------- src/abstract_tree/index_assignment.rs | 19 ++-- src/abstract_tree/map_node.rs | 12 ++- src/abstract_tree/match.rs | 7 +- src/abstract_tree/struct_definition.rs | 16 +--- src/abstract_tree/type.rs | 59 ++++++------ src/abstract_tree/value_node.rs | 23 +++-- src/built_in_functions/mod.rs | 27 +++--- src/built_in_functions/str.rs | 16 ++-- src/built_in_identifiers.rs | 29 ++++++ src/built_in_type_definitions.rs | 23 +++-- src/built_in_types.rs | 23 +++-- src/built_in_values.rs | 128 +++++-------------------- src/context.rs | 41 ++++---- src/error/runtime_error.rs | 4 +- src/error/validation_error.rs | 2 +- src/lib.rs | 1 + src/value/enum_instance.rs | 18 ++-- src/value/list.rs | 50 ++-------- src/value/map.rs | 14 +-- src/value/mod.rs | 15 +-- src/value/struct_instance.rs | 6 +- tests/value.rs | 2 +- 29 files changed, 330 insertions(+), 387 deletions(-) create mode 100644 src/built_in_identifiers.rs diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 178a5a2..fe0b1fa 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -54,14 +54,13 @@ impl AbstractTree for Assignment { fn validate(&self, source: &str, context: &Context) -> Result<(), ValidationError> { if let AssignmentOperator::Equal = self.operator { - let key = self.identifier.inner().clone(); let r#type = if let Some(definition) = &self.type_specification { definition.inner().clone() } else { self.statement.expected_type(context)? }; - context.set_type(key, r#type)?; + context.set_type(self.identifier.clone(), r#type)?; } if let Some(type_specification) = &self.type_specification { @@ -130,30 +129,33 @@ impl AbstractTree for Assignment { } fn run(&self, source: &str, context: &Context) -> Result { - let key = self.identifier.inner(); let value = self.statement.run(source, context)?; let new_value = match self.operator { AssignmentOperator::PlusEqual => { - if let Some(mut previous_value) = context.get_value(key)? { + if let Some(mut previous_value) = context.get_value(&self.identifier)? { previous_value += value; previous_value } else { - return Err(RuntimeError::VariableIdentifierNotFound(key.clone())); + return Err(RuntimeError::VariableIdentifierNotFound( + self.identifier.clone(), + )); } } AssignmentOperator::MinusEqual => { - if let Some(mut previous_value) = context.get_value(key)? { + if let Some(mut previous_value) = context.get_value(&self.identifier)? { previous_value -= value; previous_value } else { - return Err(RuntimeError::VariableIdentifierNotFound(key.clone())); + return Err(RuntimeError::VariableIdentifierNotFound( + self.identifier.clone(), + )); } } AssignmentOperator::Equal => value, }; - context.set_value(key.clone(), new_value)?; + context.set_value(self.identifier.clone(), new_value)?; Ok(Value::none()) } diff --git a/src/abstract_tree/enum_defintion.rs b/src/abstract_tree/enum_defintion.rs index 45b21d9..91b5e63 100644 --- a/src/abstract_tree/enum_defintion.rs +++ b/src/abstract_tree/enum_defintion.rs @@ -27,8 +27,8 @@ impl EnumDefinition { } } - pub fn instantiate(&self, variant: String, content: Option) -> EnumInstance { - EnumInstance::new(self.identifier.inner().clone(), variant, content) + pub fn instantiate(&self, variant: Identifier, content: Option) -> EnumInstance { + EnumInstance::new(self.identifier.clone(), variant, content) } pub fn identifier(&self) -> &Identifier { @@ -86,10 +86,7 @@ impl AbstractTree for EnumDefinition { } fn run(&self, _source: &str, context: &Context) -> Result { - context.set_definition( - self.identifier.inner().clone(), - TypeDefinition::Enum(self.clone()), - )?; + context.set_definition(self.identifier.clone(), TypeDefinition::Enum(self.clone()))?; Ok(Value::none()) } diff --git a/src/abstract_tree/for.rs b/src/abstract_tree/for.rs index 89171d6..a3f19eb 100644 --- a/src/abstract_tree/for.rs +++ b/src/abstract_tree/for.rs @@ -76,7 +76,7 @@ impl AbstractTree for For { position: self.source_position, }); }; - let key = self.item_id.inner().clone(); + let key = self.item_id.clone(); self.context.inherit_from(context)?; self.context.set_type(key, item_type)?; @@ -87,7 +87,7 @@ impl AbstractTree for For { self.context.inherit_from(context)?; let expression_run = self.collection.run(source, context)?; - let key = self.item_id.inner(); + let key = &self.item_id; if let Value::Range(range) = expression_run { if self.is_async { diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 6d9d189..b26bb4e 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -142,16 +142,11 @@ impl AbstractTree for FunctionCall { fn run(&self, source: &str, context: &Context) -> Result { let value = match &self.function_expression { FunctionExpression::Identifier(identifier) => { - let key = identifier.inner(); - - if let Some(value) = context.get_value(key)? { - self.context - .set_value(identifier.inner().clone(), value.clone())?; + if let Some(value) = context.get_value(identifier)? { + self.context.set_value(identifier.clone(), value.clone())?; value.clone() } else { - return Err(RuntimeError::VariableIdentifierNotFound( - identifier.inner().clone(), - )); + return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); } } FunctionExpression::FunctionCall(function_call) => { @@ -181,7 +176,7 @@ impl AbstractTree for FunctionCall { for (identifier, expression) in parameter_expression_pairs { let value = expression.run(source, context)?; - self.context.set_value(identifier.inner().clone(), value)?; + self.context.set_value(identifier.clone(), value)?; } function_node.call(source, &self.context) diff --git a/src/abstract_tree/function_node.rs b/src/abstract_tree/function_node.rs index 04b5197..a9199ba 100644 --- a/src/abstract_tree/function_node.rs +++ b/src/abstract_tree/function_node.rs @@ -118,7 +118,7 @@ impl AbstractTree for FunctionNode { let validation_context = Context::new(); for (parameter, r#type) in self.parameters.iter().zip(parameter_types.iter()) { - validation_context.set_type(parameter.inner().clone(), r#type.clone())?; + validation_context.set_type(parameter.clone(), r#type.clone())?; } let actual = self.body.expected_type(&validation_context)?; diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index 279fbb2..7cbf681 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -1,8 +1,12 @@ -use std::fmt::{self, Display, Formatter}; +use std::{ + fmt::{self, Display, Formatter}, + sync::Arc, +}; -use serde::{Deserialize, Serialize}; +use serde::{de::Visitor, Deserialize, Serialize}; use crate::{ + built_in_identifiers::all_built_in_identifiers, error::{RuntimeError, SyntaxError, ValidationError}, AbstractTree, Context, Format, SyntaxNode, Type, Value, }; @@ -10,22 +14,30 @@ use crate::{ /// A string by which a variable is known to a context. /// /// Every variable is a key-value pair. An identifier holds the key part of that -/// pair. Its inner value can be used to retrieve a Value instance from a Map. -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)] -pub struct Identifier(String); +/// pair and can be used to retrieve a Value instance from a Map or Context. +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub struct Identifier(Arc); impl Identifier { - pub fn new>(inner: T) -> Self { - Identifier(inner.into()) + pub fn new(key: &str) -> Self { + for built_in_identifier in all_built_in_identifiers() { + let identifier = built_in_identifier.get(); + + if &key == identifier.inner().as_ref() { + return identifier.clone(); + } + } + + Identifier(Arc::new(key.to_string())) } - pub fn take_inner(self) -> String { - self.0 - } - - pub fn inner(&self) -> &String { + pub fn inner(&self) -> &Arc { &self.0 } + + pub fn contains(&self, string: &str) -> bool { + self.0.as_ref() == string + } } impl AbstractTree for Identifier { @@ -40,7 +52,7 @@ impl AbstractTree for Identifier { debug_assert!(!text.is_empty()); - Ok(Identifier(text.to_string())) + Ok(Identifier::new(text)) } fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> { @@ -48,7 +60,7 @@ impl AbstractTree for Identifier { } fn expected_type(&self, context: &Context) -> Result { - if let Some(r#type) = context.get_type(&self.0)? { + if let Some(r#type) = context.get_type(self)? { Ok(r#type) } else { Err(ValidationError::VariableIdentifierNotFound(self.clone())) @@ -56,10 +68,10 @@ impl AbstractTree for Identifier { } fn run(&self, _source: &str, context: &Context) -> Result { - if let Some(value) = context.get_value(&self.0)? { + if let Some(value) = context.get_value(self)? { Ok(value.clone()) } else { - Err(RuntimeError::VariableIdentifierNotFound(self.0.clone())) + Err(RuntimeError::VariableIdentifierNotFound(self.clone())) } } } @@ -75,3 +87,38 @@ impl Display for Identifier { write!(f, "{}", self.0) } } + +impl Serialize for Identifier { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.0.as_ref()) + } +} + +impl<'de> Deserialize<'de> for Identifier { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_string(IdentifierVisitor) + } +} + +struct IdentifierVisitor; + +impl<'de> Visitor<'de> for IdentifierVisitor { + type Value = Identifier; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("valid UFT-8 sequence") + } + + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error, + { + Ok(Identifier(Arc::new(v))) + } +} diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index fcdd425..f59df4b 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize}; use crate::{ error::{RuntimeError, SyntaxError, ValidationError}, - AbstractTree, Context, Format, IndexExpression, List, SourcePosition, SyntaxNode, Type, Value, + AbstractTree, Context, Format, Identifier, IndexExpression, SourcePosition, SyntaxNode, Type, + Value, }; /// Abstract representation of an index expression. @@ -12,7 +13,6 @@ use crate::{ pub struct Index { pub collection: IndexExpression, pub index: IndexExpression, - pub index_end: Option, source_position: SourcePosition, } @@ -26,21 +26,9 @@ impl AbstractTree for Index { let index_node = node.child(2).unwrap(); let index = IndexExpression::from_syntax(index_node, source, context)?; - let index_end_node = node.child(4); - let index_end = if let Some(index_end_node) = index_end_node { - Some(IndexExpression::from_syntax( - index_end_node, - source, - context, - )?) - } else { - None - }; - Ok(Index { collection, index, - index_end, source_position: SourcePosition::from(node.range()), }) } @@ -58,10 +46,6 @@ impl AbstractTree for Index { self.collection.validate(_source, _context)?; self.index.validate(_source, _context)?; - if let Some(index_end) = &self.index_end { - index_end.validate(_source, _context)?; - } - Ok(()) } @@ -71,36 +55,28 @@ impl AbstractTree for Index { match value { Value::List(list) => { let index = self.index.run(source, context)?.as_integer()? as usize; - - let item = if let Some(index_end) = &self.index_end { - let index_end = index_end.run(source, context)?.as_integer()? as usize; - let sublist = list.items()[index..=index_end].to_vec(); - - Value::List(List::with_items(sublist)) - } else { - list.items().get(index).cloned().unwrap_or_default() - }; + let item = list.items().get(index).cloned().unwrap_or_default(); Ok(item) } Value::Map(map) => { let map = map.inner(); - let (key, value) = if let IndexExpression::Identifier(identifier) = &self.index { - let key = identifier.inner(); - let value = map.get(key).unwrap_or_default(); + let (identifier, value) = + if let IndexExpression::Identifier(identifier) = &self.index { + let value = map.get(identifier).unwrap_or_default(); - (key.clone(), value) - } else { - let index_value = self.index.run(source, context)?; - let key = index_value.as_string()?; - let value = map.get(key.as_str()).unwrap_or_default(); + (identifier.clone(), value) + } else { + let index_value = self.index.run(source, context)?; + let identifier = Identifier::new(index_value.as_string()?); + let value = map.get(&identifier).unwrap_or_default(); - (key.clone(), value) - }; + (identifier, value) + }; if value.is_none() { - Err(RuntimeError::VariableIdentifierNotFound(key)) + Err(RuntimeError::VariableIdentifierNotFound(identifier)) } else { Ok(value.clone()) } @@ -121,10 +97,5 @@ impl Format for Index { self.collection.format(output, indent_level); output.push(':'); self.index.format(output, indent_level); - - if let Some(expression) = &self.index_end { - output.push_str(".."); - expression.format(output, indent_level); - } } } diff --git a/src/abstract_tree/index_assignment.rs b/src/abstract_tree/index_assignment.rs index 32e946d..052df52 100644 --- a/src/abstract_tree/index_assignment.rs +++ b/src/abstract_tree/index_assignment.rs @@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize}; use crate::{ error::{RuntimeError, SyntaxError, ValidationError}, - AbstractTree, AssignmentOperator, Context, Format, Index, IndexExpression, Statement, - SyntaxNode, Type, Value, + AbstractTree, AssignmentOperator, Context, Format, Identifier, Index, IndexExpression, + Statement, SyntaxNode, Type, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -44,11 +44,14 @@ impl AbstractTree for IndexAssignment { fn run(&self, source: &str, context: &Context) -> Result { let _index_collection = self.index.collection.run(source, context)?; - let index_key = if let IndexExpression::Identifier(identifier) = &self.index.index { - identifier.inner() + let index_identifier = if let IndexExpression::Identifier(identifier) = &self.index.index { + identifier } else { + let index_run = self.index.index.run(source, context)?; + let expected_identifier = Identifier::new(index_run.as_string()?); + return Err(RuntimeError::VariableIdentifierNotFound( - self.index.index.run(source, context)?.to_string(), + expected_identifier, )); }; @@ -56,7 +59,7 @@ impl AbstractTree for IndexAssignment { let new_value = match self.operator { AssignmentOperator::PlusEqual => { - if let Some(mut previous_value) = context.get_value(index_key)? { + if let Some(mut previous_value) = context.get_value(index_identifier)? { previous_value += value; previous_value } else { @@ -64,7 +67,7 @@ impl AbstractTree for IndexAssignment { } } AssignmentOperator::MinusEqual => { - if let Some(mut previous_value) = context.get_value(index_key)? { + if let Some(mut previous_value) = context.get_value(index_identifier)? { previous_value -= value; previous_value } else { @@ -74,7 +77,7 @@ impl AbstractTree for IndexAssignment { AssignmentOperator::Equal => value, }; - context.set_value(index_key.clone(), new_value)?; + context.set_value(index_identifier.clone(), new_value)?; Ok(Value::none()) } diff --git a/src/abstract_tree/map_node.rs b/src/abstract_tree/map_node.rs index 71fd221..56c29f1 100644 --- a/src/abstract_tree/map_node.rs +++ b/src/abstract_tree/map_node.rs @@ -11,12 +11,12 @@ use crate::{ #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct MapNode { - properties: BTreeMap)>, + properties: BTreeMap)>, position: SourcePosition, } impl MapNode { - pub fn properties(&self) -> &BTreeMap)> { + pub fn properties(&self) -> &BTreeMap)> { &self.properties } } @@ -26,14 +26,14 @@ impl AbstractTree for MapNode { SyntaxError::expect_syntax_node(source, "map", node)?; let mut properties = BTreeMap::new(); - let mut current_key = "".to_string(); + let mut current_identifier = None; let mut current_type = None; for index in 0..node.child_count() - 1 { let child = node.child(index).unwrap(); if child.kind() == "identifier" { - current_key = Identifier::from_syntax(child, source, context)?.take_inner(); + current_identifier = Some(Identifier::from_syntax(child, source, context)?); current_type = None; } @@ -45,7 +45,9 @@ impl AbstractTree for MapNode { if child.kind() == "statement" { let statement = Statement::from_syntax(child, source, context)?; - properties.insert(current_key.clone(), (statement, current_type.clone())); + if let Some(identifier) = ¤t_identifier { + properties.insert(identifier.clone(), (statement, current_type.clone())); + } } } diff --git a/src/abstract_tree/match.rs b/src/abstract_tree/match.rs index 0c95cf7..681e897 100644 --- a/src/abstract_tree/match.rs +++ b/src/abstract_tree/match.rs @@ -84,16 +84,15 @@ impl AbstractTree for Match { if let (Value::Enum(enum_instance), MatchPattern::EnumPattern(enum_pattern)) = (&matcher_value, pattern) { - if enum_instance.name() == enum_pattern.name().inner() - && enum_instance.variant_name() == enum_pattern.variant().inner() + if enum_instance.name() == enum_pattern.name() + && enum_instance.variant() == enum_pattern.variant() { let statement_context = Context::with_variables_from(context)?; if let (Some(identifier), Some(value)) = (enum_pattern.inner_identifier(), enum_instance.value()) { - statement_context - .set_value(identifier.inner().clone(), value.as_ref().clone())?; + statement_context.set_value(identifier.clone(), value.as_ref().clone())?; } return statement.run(source, &statement_context); diff --git a/src/abstract_tree/struct_definition.rs b/src/abstract_tree/struct_definition.rs index b99d540..4284bd7 100644 --- a/src/abstract_tree/struct_definition.rs +++ b/src/abstract_tree/struct_definition.rs @@ -12,7 +12,7 @@ use crate::{ #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct StructDefinition { name: Identifier, - properties: BTreeMap, Type)>, + properties: BTreeMap, Type)>, } impl StructDefinition { @@ -38,10 +38,7 @@ impl StructDefinition { all_properties.set(key.clone(), value); } - Ok(StructInstance::new( - self.name.inner().clone(), - all_properties, - )) + Ok(StructInstance::new(self.name.clone(), all_properties)) } } @@ -63,7 +60,7 @@ impl AbstractTree for StructDefinition { if child_syntax_node.kind() == "identifier" { if current_statement.is_none() { if let (Some(identifier), Some(r#type)) = (¤t_identifier, ¤t_type) { - properties.insert(identifier.inner().clone(), (None, r#type.clone())); + properties.insert(identifier.clone(), (None, r#type.clone())); } } @@ -91,7 +88,7 @@ impl AbstractTree for StructDefinition { }; properties.insert( - identifier.inner().clone(), + identifier.clone(), (current_statement.clone(), r#type.clone()), ); } @@ -110,10 +107,7 @@ impl AbstractTree for StructDefinition { } fn run(&self, _source: &str, context: &Context) -> Result { - context.set_definition( - self.name.inner().clone(), - TypeDefinition::Struct(self.clone()), - )?; + context.set_definition(self.name.clone(), TypeDefinition::Struct(self.clone()))?; Ok(Value::none()) } diff --git a/src/abstract_tree/type.rs b/src/abstract_tree/type.rs index 5058e59..67bb5d2 100644 --- a/src/abstract_tree/type.rs +++ b/src/abstract_tree/type.rs @@ -1,11 +1,12 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; +use tree_sitter::Node as SyntaxNode; use crate::{ built_in_types::BuiltInType, error::{RuntimeError, SyntaxError, ValidationError}, - AbstractTree, Context, Format, Identifier, SyntaxNode, Value, + AbstractTree, Context, Format, Identifier, Value, }; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] @@ -13,10 +14,9 @@ pub enum Type { Any, Boolean, Collection, - Custom(Identifier), - CustomWithArgument { + Custom { name: Identifier, - argument: Box, + argument: Option>, }, Float, Function { @@ -33,8 +33,15 @@ pub enum Type { } impl Type { + pub fn custom(name: Identifier, argument: Option) -> Self { + Type::Custom { + name, + argument: argument.map(|r#type| Box::new(r#type)), + } + } + pub fn option(inner_type: Option) -> Self { - BuiltInType::Option.get(inner_type).clone() + BuiltInType::Option(inner_type).get().clone() } pub fn list(item_type: Type) -> Self { @@ -75,13 +82,12 @@ impl Type { | (Type::Integer, Type::Number) | (Type::Float, Type::Number) | (Type::String, Type::String) => true, - (Type::Custom(left), Type::Custom(right)) => left == right, ( - Type::CustomWithArgument { + Type::Custom { name: left_name, argument: left_argument, }, - Type::CustomWithArgument { + Type::Custom { name: right_name, argument: right_argument, }, @@ -138,7 +144,7 @@ impl AbstractTree for Type { fn from_syntax( node: SyntaxNode, _source: &str, - _context: &Context, + context: &Context, ) -> Result { SyntaxError::expect_syntax_node(_source, "type", node)?; @@ -146,23 +152,18 @@ impl AbstractTree for Type { let r#type = match type_node.kind() { "identifier" => { - if node.child_count() == 1 { - Type::Custom(Identifier::from_syntax(type_node, _source, _context)?) + let name = Identifier::from_syntax(type_node, _source, context)?; + let argument = if let Some(child) = node.child(2) { + Some(Type::from_syntax(child, _source, context)?) } else { - let name = Identifier::from_syntax(type_node, _source, _context)?; + None + }; - let argument_node = node.child(2).unwrap(); - let argument = Type::from_syntax(argument_node, _source, _context)?; - - Type::CustomWithArgument { - name, - argument: Box::new(argument), - } - } + Type::custom(name, argument) } "[" => { let item_type_node = node.child(1).unwrap(); - let item_type = Type::from_syntax(item_type_node, _source, _context)?; + let item_type = Type::from_syntax(item_type_node, _source, context)?; Type::List(Box::new(item_type)) } @@ -178,7 +179,7 @@ impl AbstractTree for Type { let child = node.child(index).unwrap(); if child.is_named() { - let parameter_type = Type::from_syntax(child, _source, _context)?; + let parameter_type = Type::from_syntax(child, _source, context)?; parameter_types.push(parameter_type); } @@ -186,7 +187,7 @@ impl AbstractTree for Type { let final_node = node.child(child_count - 1).unwrap(); let return_type = if final_node.is_named() { - Type::from_syntax(final_node, _source, _context)? + Type::from_syntax(final_node, _source, context)? } else { Type::option(None) }; @@ -233,8 +234,7 @@ impl Format for Type { Type::Any => output.push_str("any"), Type::Boolean => output.push_str("bool"), Type::Collection => output.push_str("collection"), - Type::Custom(_) => todo!(), - Type::CustomWithArgument { + Type::Custom { name: _, argument: _, } => todo!(), @@ -279,9 +279,12 @@ impl Display for Type { Type::Any => write!(f, "any"), Type::Boolean => write!(f, "bool"), Type::Collection => write!(f, "collection"), - Type::Custom(identifier) => write!(f, "{identifier}"), - Type::CustomWithArgument { name, argument } => { - write!(f, "{name}<{argument}>") + Type::Custom { name, argument } => { + if let Some(argument) = argument { + write!(f, "{name}<{argument}>") + } else { + write!(f, "{name}") + } } Type::Float => write!(f, "float"), Type::Function { diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index de0312a..5b410a3 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -121,7 +121,7 @@ impl AbstractTree for ValueNode { let r#type = match self { ValueNode::Boolean(_) => Type::Boolean, ValueNode::Float(_) => Type::Float, - ValueNode::Function(function) => function.r#type().clone(), + ValueNode::Function(function) => function.r#type(), ValueNode::Integer(_) => Type::Integer, ValueNode::String(_) => Type::String, ValueNode::List(expressions) => { @@ -147,17 +147,20 @@ impl AbstractTree for ValueNode { } ValueNode::Map(_) => Type::Map, ValueNode::Struct { name, .. } => { - Type::Custom(name.clone()) + Type::Custom { name: name.clone(), argument: None } } ValueNode::Range(_) => Type::Range, ValueNode::Enum { name, variant: _, expression } => { if let Some(expression) = expression { - Type::CustomWithArgument { + Type::Custom { name: name.clone(), - argument: Box::new(expression.expected_type(context)?) + argument: Some(Box::new(expression.expected_type(context)?)) } } else { - Type::Custom(name.clone()) + Type::Custom{ + name: name.clone(), + argument: None, + } } }, }; @@ -204,7 +207,7 @@ impl AbstractTree for ValueNode { ValueNode::Map(map_node) => map_node.run(source, context)?, ValueNode::Range(range) => Value::Range(range.clone()), ValueNode::Struct { name, properties } => { - let instance = if let Some(definition) = context.get_definition(name.inner())? { + let instance = if let Some(definition) = context.get_definition(name)? { if let TypeDefinition::Struct(struct_definition) = definition { struct_definition.instantiate(properties, source, context)? } else { @@ -212,7 +215,7 @@ impl AbstractTree for ValueNode { } } else { return Err(RuntimeError::ValidationFailure( - ValidationError::TypeDefinitionNotFound(name.inner().clone()) + ValidationError::TypeDefinitionNotFound(name.clone()) )); }; @@ -225,9 +228,9 @@ impl AbstractTree for ValueNode { } else { Value::none() }; - let instance = if let Some(definition) = context.get_definition(name.inner())? { + let instance = if let Some(definition) = context.get_definition(name)? { if let TypeDefinition::Enum(enum_defintion) = definition { - enum_defintion.instantiate(variant.inner().clone(), Some(value)) + enum_defintion.instantiate(variant.clone(), Some(value)) } else { return Err(RuntimeError::ValidationFailure( ValidationError::ExpectedEnumDefintion { @@ -237,7 +240,7 @@ impl AbstractTree for ValueNode { } } else { return Err(RuntimeError::ValidationFailure( - ValidationError::TypeDefinitionNotFound(name.inner().clone()) + ValidationError::TypeDefinitionNotFound(name.clone()) )); }; diff --git a/src/built_in_functions/mod.rs b/src/built_in_functions/mod.rs index 6462ad6..833dbdc 100644 --- a/src/built_in_functions/mod.rs +++ b/src/built_in_functions/mod.rs @@ -19,7 +19,7 @@ pub trait Callable { &self, arguments: &[Value], source: &str, - outer_context: &Context, + context: &Context, ) -> Result; } @@ -72,7 +72,10 @@ impl Callable for BuiltInFunction { match self { BuiltInFunction::AssertEqual => Type::function( vec![Type::Any, Type::Any], - Type::Custom(Identifier::new("Result")), + Type::Custom { + name: Identifier::new("Result"), + argument: None, + }, ), BuiltInFunction::Fs(fs_function) => fs_function.r#type(), BuiltInFunction::Json(json_function) => json_function.r#type(), @@ -90,7 +93,7 @@ impl Callable for BuiltInFunction { &self, arguments: &[Value], _source: &str, - _outer_context: &Context, + context: &Context, ) -> Result { match self { BuiltInFunction::AssertEqual => { @@ -101,26 +104,22 @@ impl Callable for BuiltInFunction { let result = if left == right { Value::Enum(EnumInstance::new( - "Result".to_string(), - "Ok".to_string(), + Identifier::new("Result"), + Identifier::new("Ok"), Some(Value::none()), )) } else { Value::Enum(EnumInstance::new( - "Result".to_string(), - "Error".to_string(), + Identifier::new("Result"), + Identifier::new("Error"), Some(Value::none()), )) }; Ok(result) } - BuiltInFunction::Fs(fs_function) => { - fs_function.call(arguments, _source, _outer_context) - } - BuiltInFunction::Json(json_function) => { - json_function.call(arguments, _source, _outer_context) - } + BuiltInFunction::Fs(fs_function) => fs_function.call(arguments, _source, context), + BuiltInFunction::Json(json_function) => json_function.call(arguments, _source, context), BuiltInFunction::Length => { RuntimeError::expect_argument_amount(self.name(), 1, arguments.len())?; @@ -184,7 +183,7 @@ impl Callable for BuiltInFunction { Ok(Value::Integer(random())) } BuiltInFunction::String(string_function) => { - string_function.call(arguments, _source, _outer_context) + string_function.call(arguments, _source, context) } } } diff --git a/src/built_in_functions/str.rs b/src/built_in_functions/str.rs index 9ef4eed..331e9da 100644 --- a/src/built_in_functions/str.rs +++ b/src/built_in_functions/str.rs @@ -1,7 +1,7 @@ use enum_iterator::Sequence; use serde::{Deserialize, Serialize}; -use crate::{error::RuntimeError, Context, EnumInstance, List, Type, Value}; +use crate::{error::RuntimeError, Context, EnumInstance, Identifier, List, Type, Value}; use super::Callable; @@ -203,7 +203,7 @@ impl Callable for StrFunction { &self, arguments: &[Value], _source: &str, - _outer_context: &Context, + context: &Context, ) -> Result { let value = match self { StrFunction::AsBytes => { @@ -238,14 +238,14 @@ impl Callable for StrFunction { if let Some(index) = find { Value::Enum(EnumInstance::new( - "Option".to_string(), - "Some".to_string(), + Identifier::new("Option"), + Identifier::new("Some"), Some(index), )) } else { Value::Enum(EnumInstance::new( - "Option".to_string(), - "None".to_string(), + Identifier::new("Option"), + Identifier::new("None"), Some(Value::none()), )) } @@ -477,8 +477,8 @@ impl Callable for StrFunction { if let Some(value) = stripped { Value::Enum(EnumInstance::new( - "Option".to_string(), - "Some".to_string(), + Identifier::new("Option"), + Identifier::new("Some"), Some(value), )) } else { diff --git a/src/built_in_identifiers.rs b/src/built_in_identifiers.rs new file mode 100644 index 0000000..7c6918f --- /dev/null +++ b/src/built_in_identifiers.rs @@ -0,0 +1,29 @@ +use std::sync::OnceLock; + +use enum_iterator::{all, Sequence}; + +use crate::Identifier; + +pub fn all_built_in_identifiers() -> impl Iterator { + all() +} + +const OPTION: OnceLock = OnceLock::new(); +const NONE: OnceLock = OnceLock::new(); + +#[derive(Sequence)] +pub enum BuiltInIdentifier { + Option, + None, +} + +impl BuiltInIdentifier { + pub fn get(&self) -> &Identifier { + match self { + BuiltInIdentifier::Option => { + return OPTION.get_or_init(|| Identifier::new("Option")); + } + BuiltInIdentifier::None => return NONE.get_or_init(|| Identifier::new("None")), + } + } +} diff --git a/src/built_in_type_definitions.rs b/src/built_in_type_definitions.rs index 7a33962..e3cab3d 100644 --- a/src/built_in_type_definitions.rs +++ b/src/built_in_type_definitions.rs @@ -2,10 +2,13 @@ use std::sync::OnceLock; use enum_iterator::{all, Sequence}; -use crate::{EnumDefinition, Identifier, Type, TypeDefinition, VariantContent}; +use crate::{ + error::rw_lock_error::RwLockError, Context, EnumDefinition, Identifier, Type, TypeDefinition, + VariantContent, +}; -static OPTION: OnceLock = OnceLock::new(); -static RESULT: OnceLock = OnceLock::new(); +static OPTION: OnceLock> = OnceLock::new(); +static RESULT: OnceLock> = OnceLock::new(); pub fn all_built_in_type_definitions() -> impl Iterator { all() @@ -25,25 +28,29 @@ impl BuiltInTypeDefinition { } } - pub fn get(&self) -> &TypeDefinition { + pub fn get(&self, context: &Context) -> &Result { match self { BuiltInTypeDefinition::Option => OPTION.get_or_init(|| { - TypeDefinition::Enum(EnumDefinition::new( + let definition = TypeDefinition::Enum(EnumDefinition::new( Identifier::new(self.name()), vec![ (Identifier::new("Some"), VariantContent::Type(Type::Any)), (Identifier::new("None"), VariantContent::None), ], - )) + )); + + Ok(definition) }), BuiltInTypeDefinition::Result => RESULT.get_or_init(|| { - TypeDefinition::Enum(EnumDefinition::new( + let definition = TypeDefinition::Enum(EnumDefinition::new( Identifier::new(self.name()), vec![ (Identifier::new("Ok"), VariantContent::Type(Type::Any)), (Identifier::new("Err"), VariantContent::Type(Type::Any)), ], - )) + )); + + Ok(definition) }), } } diff --git a/src/built_in_types.rs b/src/built_in_types.rs index a12ae3d..3181299 100644 --- a/src/built_in_types.rs +++ b/src/built_in_types.rs @@ -1,34 +1,33 @@ use std::sync::OnceLock; -use enum_iterator::Sequence; -use serde::{Deserialize, Serialize}; - use crate::{Identifier, Type}; static OPTION: OnceLock = OnceLock::new(); -#[derive(Sequence, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum BuiltInType { - Option, + Option(Option), } impl BuiltInType { pub fn name(&self) -> &'static str { match self { - BuiltInType::Option => todo!(), + BuiltInType::Option(_) => "Option", } } - pub fn get(&self, inner_type: Option) -> &Type { + pub fn get(&self) -> &Type { match self { - BuiltInType::Option => OPTION.get_or_init(|| { - if let Some(inner_type) = inner_type { - Type::CustomWithArgument { + BuiltInType::Option(content_type) => OPTION.get_or_init(|| { + if let Some(content_type) = content_type { + Type::Custom { name: Identifier::new("Option"), - argument: Box::new(inner_type), + argument: Some(Box::new(content_type.clone())), } } else { - Type::Custom(Identifier::new("Option")) + Type::Custom { + name: Identifier::new("Option"), + argument: None, + } } }), } diff --git a/src/built_in_values.rs b/src/built_in_values.rs index f502601..2e293b9 100644 --- a/src/built_in_values.rs +++ b/src/built_in_values.rs @@ -1,21 +1,19 @@ -use std::{collections::BTreeMap, env::args, sync::OnceLock}; +use std::{env::args, sync::OnceLock}; use enum_iterator::{all, Sequence}; use serde::{Deserialize, Serialize}; use crate::{ built_in_functions::{fs::fs_functions, json::json_functions, str::string_functions, Callable}, - error::{RuntimeError, SyntaxError, ValidationError}, - AbstractTree, BuiltInFunction, Context, EnumInstance, Format, Function, Identifier, List, Map, - SyntaxNode, Type, Value, + BuiltInFunction, EnumInstance, Function, Identifier, List, Map, Value, }; static ARGS: OnceLock = OnceLock::new(); static FS: OnceLock = OnceLock::new(); static JSON: OnceLock = OnceLock::new(); -static RANDOM: OnceLock = OnceLock::new(); -static STRING: OnceLock = OnceLock::new(); static NONE: OnceLock = OnceLock::new(); +static RANDOM: OnceLock = OnceLock::new(); +static STR: OnceLock = OnceLock::new(); /// Returns the entire built-in value API. pub fn all_built_in_values() -> impl Iterator { @@ -86,23 +84,6 @@ impl BuiltInValue { } } - /// Returns the value's type. - /// - /// This is checked with a unit test to ensure it matches the value. - pub fn r#type(&self) -> Type { - match self { - BuiltInValue::Args => Type::list(Type::String), - BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(), - BuiltInValue::Fs => Type::Map, - BuiltInValue::Json => Type::Map, - BuiltInValue::Length => BuiltInFunction::Length.r#type(), - BuiltInValue::None => Type::Custom(Identifier::new("Option")), - BuiltInValue::Output => BuiltInFunction::Output.r#type(), - BuiltInValue::Random => Type::Map, - BuiltInValue::Str => Type::Map, - } - } - /// Returns the value by creating it or, if it has already been accessed, retrieving it from its /// [OnceLock][]. pub fn get(&self) -> &Value { @@ -116,42 +97,40 @@ impl BuiltInValue { &Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual)) } BuiltInValue::Fs => FS.get_or_init(|| { - let mut fs_context = BTreeMap::new(); + let mut fs_map = Map::new(); for fs_function in fs_functions() { - let key = fs_function.name().to_string(); + let key = fs_function.name(); let value = Value::Function(Function::BuiltIn(BuiltInFunction::Fs(fs_function))); - fs_context.insert(key, value); + fs_map.set(Identifier::new(key), value); } - Value::Map(Map::with_values(fs_context)) + Value::Map(fs_map) }), BuiltInValue::Json => JSON.get_or_init(|| { - let mut json_context = BTreeMap::new(); + let mut json_map = Map::new(); for json_function in json_functions() { - let key = json_function.name().to_string(); + let key = json_function.name(); let value = Value::Function(Function::BuiltIn(BuiltInFunction::Json(json_function))); - json_context.insert(key, value); + json_map.set(Identifier::new(key), value); } - Value::Map(Map::with_values(json_context)) + Value::Map(json_map) }), BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)), - BuiltInValue::None => NONE.get_or_init(|| { - Value::Enum(EnumInstance::new( - "Option".to_string(), - "None".to_string(), - None, - )) - }), + BuiltInValue::None => &Value::Enum(EnumInstance::new( + Identifier::new("Option"), + Identifier::new("None"), + None, + )), BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)), BuiltInValue::Random => RANDOM.get_or_init(|| { - let mut random_context = BTreeMap::new(); + let mut random_map = Map::new(); for built_in_function in [ BuiltInFunction::RandomBoolean, @@ -159,83 +138,28 @@ impl BuiltInValue { BuiltInFunction::RandomFrom, BuiltInFunction::RandomInteger, ] { - let key = built_in_function.name().to_string(); + let identifier = Identifier::new(built_in_function.name()); let value = Value::Function(Function::BuiltIn(built_in_function)); - random_context.insert(key, value); + random_map.set(identifier, value); } - Value::Map(Map::with_values(random_context)) + Value::Map(random_map) }), - BuiltInValue::Str => STRING.get_or_init(|| { - let mut string_context = BTreeMap::new(); + BuiltInValue::Str => STR.get_or_init(|| { + let mut str_map = Map::new(); for string_function in string_functions() { - let key = string_function.name().to_string(); + let identifier = Identifier::new(string_function.name()); let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( string_function, ))); - string_context.insert(key, value); + str_map.set(identifier, value); } - Value::Map(Map::with_values(string_context)) + Value::Map(str_map) }), } } } - -impl AbstractTree for BuiltInValue { - fn from_syntax( - node: SyntaxNode, - _source: &str, - _context: &Context, - ) -> Result { - let built_in_value = match node.kind() { - "args" => BuiltInValue::Args, - "assert_equal" => BuiltInValue::AssertEqual, - "fs" => BuiltInValue::Fs, - "json" => BuiltInValue::Json, - "length" => BuiltInValue::Length, - "output" => BuiltInValue::Output, - "random" => BuiltInValue::Random, - "str" => BuiltInValue::Str, - _ => todo!(), - }; - - Ok(built_in_value) - } - - fn expected_type(&self, _context: &Context) -> Result { - Ok(self.r#type()) - } - - fn validate(&self, _source: &str, _context: &Context) -> Result<(), ValidationError> { - Ok(()) - } - - fn run(&self, _source: &str, _context: &Context) -> Result { - Ok(self.get().clone()) - } -} - -impl Format for BuiltInValue { - fn format(&self, output: &mut String, _indent_level: u8) { - output.push_str(&self.get().to_string()); - } -} - -#[cfg(test)] -mod tests { - use super::all_built_in_values; - - #[test] - fn check_built_in_types() { - for built_in_value in all_built_in_values() { - let expected = built_in_value.r#type(); - let actual = built_in_value.get().r#type(); - - assert_eq!(expected, actual); - } - } -} diff --git a/src/context.rs b/src/context.rs index 5614de9..8741f7b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -35,7 +35,7 @@ use std::{ use crate::{ built_in_type_definitions::all_built_in_type_definitions, built_in_values::all_built_in_values, - error::rw_lock_error::RwLockError, Type, TypeDefinition, Value, + error::rw_lock_error::RwLockError, Identifier, Type, TypeDefinition, Value, }; /// An execution context that variable and type data during the [Interpreter]'s @@ -44,7 +44,7 @@ use crate::{ /// See the [module-level docs][self] for more info. #[derive(Clone, Debug)] pub struct Context { - inner: Arc>>, + inner: Arc>>, } impl Context { @@ -56,7 +56,7 @@ impl Context { } /// Return a lock guard to the inner BTreeMap. - pub fn inner(&self) -> Result>, RwLockError> { + pub fn inner(&self) -> Result>, RwLockError> { Ok(self.inner.read()?) } @@ -112,15 +112,15 @@ impl Context { /// /// This will also return a built-in value if one matches the key. See the /// [module-level docs][self] for more info. - pub fn get_value(&self, key: &str) -> Result, RwLockError> { - if let Some(value_data) = self.inner.read()?.get(key) { + pub fn get_value(&self, identifier: &Identifier) -> Result, RwLockError> { + if let Some(value_data) = self.inner.read()?.get(identifier) { if let ValueData::Value { inner, .. } = value_data { return Ok(Some(inner.clone())); } } for built_in_value in all_built_in_values() { - if key == built_in_value.name() { + if built_in_value.name() == identifier.inner().as_ref() { return Ok(Some(built_in_value.get().clone())); } } @@ -132,8 +132,8 @@ impl Context { /// /// If the key matches a stored value, its type will be returned. It if /// matches a type hint, the type hint will be returned. - pub fn get_type(&self, key: &str) -> Result, RwLockError> { - if let Some(value_data) = self.inner.read()?.get(key) { + pub fn get_type(&self, identifier: &Identifier) -> Result, RwLockError> { + if let Some(value_data) = self.inner.read()?.get(identifier) { match value_data { ValueData::Value { inner, .. } => return Ok(Some(inner.r#type())), ValueData::TypeHint { inner, .. } => return Ok(Some(inner.clone())), @@ -141,12 +141,6 @@ impl Context { } } - for built_in_value in all_built_in_values() { - if key == built_in_value.name() { - return Ok(Some(built_in_value.r#type())); - } - } - Ok(None) } @@ -154,16 +148,19 @@ impl Context { /// /// This will also return a built-in type definition if one matches the key. /// See the [module-level docs][self] for more info. - pub fn get_definition(&self, key: &str) -> Result, RwLockError> { - if let Some(value_data) = self.inner.read()?.get(key) { + pub fn get_definition( + &self, + identifier: &Identifier, + ) -> Result, RwLockError> { + if let Some(value_data) = self.inner.read()?.get(identifier) { if let ValueData::TypeDefinition(definition) = value_data { return Ok(Some(definition.clone())); } } for built_in_definition in all_built_in_type_definitions() { - if key == built_in_definition.name() { - return Ok(Some(built_in_definition.get().clone())); + if built_in_definition.name() == identifier.inner().as_ref() { + return Ok(Some(built_in_definition.get(self).clone()?)); } } @@ -171,7 +168,7 @@ impl Context { } /// Set a value to a key. - pub fn set_value(&self, key: String, value: Value) -> Result<(), RwLockError> { + pub fn set_value(&self, key: Identifier, value: Value) -> Result<(), RwLockError> { self.inner.write()?.insert( key, ValueData::Value { @@ -187,7 +184,7 @@ impl Context { /// /// This allows the interpreter to check a value's type before the value /// actually exists by predicting what the abstract tree will produce. - pub fn set_type(&self, key: String, r#type: Type) -> Result<(), RwLockError> { + pub fn set_type(&self, key: Identifier, r#type: Type) -> Result<(), RwLockError> { self.inner .write()? .insert(key, ValueData::TypeHint { inner: r#type }); @@ -201,7 +198,7 @@ impl Context { /// later while using this context. pub fn set_definition( &self, - key: String, + key: Identifier, definition: TypeDefinition, ) -> Result<(), RwLockError> { self.inner @@ -212,7 +209,7 @@ impl Context { } /// Remove a key-value pair. - pub fn unset(&self, key: &str) -> Result<(), RwLockError> { + pub fn unset(&self, key: &Identifier) -> Result<(), RwLockError> { self.inner.write()?.remove(key); Ok(()) diff --git a/src/error/runtime_error.rs b/src/error/runtime_error.rs index 8c6821d..8137af7 100644 --- a/src/error/runtime_error.rs +++ b/src/error/runtime_error.rs @@ -7,7 +7,7 @@ use std::{ time, }; -use crate::{Type, Value}; +use crate::{Identifier, Type, Value}; use super::{rw_lock_error::RwLockError, ValidationError}; @@ -106,7 +106,7 @@ pub enum RuntimeError { Utf8(FromUtf8Error), /// Failed to find a variable with a value for this key. - VariableIdentifierNotFound(String), + VariableIdentifierNotFound(Identifier), /// A built-in function was called with the wrong amount of arguments. ExpectedBuiltInFunctionArgumentAmount { diff --git a/src/error/validation_error.rs b/src/error/validation_error.rs index 0f0bc29..25a9876 100644 --- a/src/error/validation_error.rs +++ b/src/error/validation_error.rs @@ -65,7 +65,7 @@ pub enum ValidationError { VariableIdentifierNotFound(Identifier), /// Failed to find a type definition with this key. - TypeDefinitionNotFound(String), + TypeDefinitionNotFound(Identifier), /// Failed to find an enum definition with this key. ExpectedEnumDefintion { actual: TypeDefinition }, diff --git a/src/lib.rs b/src/lib.rs index d7d7bb6..7e1361f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ pub use tree_sitter::Node as SyntaxNode; pub mod abstract_tree; pub mod built_in_functions; +pub mod built_in_identifiers; pub mod built_in_type_definitions; pub mod built_in_types; pub mod built_in_values; diff --git a/src/value/enum_instance.rs b/src/value/enum_instance.rs index df3d089..35ec5db 100644 --- a/src/value/enum_instance.rs +++ b/src/value/enum_instance.rs @@ -2,30 +2,30 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; -use crate::Value; +use crate::{Identifier, Value}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct EnumInstance { - name: String, - variant_name: String, + name: Identifier, + variant: Identifier, value: Option>, } impl EnumInstance { - pub fn new(name: String, variant_name: String, value: Option) -> Self { + pub fn new(name: Identifier, variant_name: Identifier, value: Option) -> Self { Self { name, - variant_name, + variant: variant_name, value: value.map(|value| Box::new(value)), } } - pub fn name(&self) -> &String { + pub fn name(&self) -> &Identifier { &self.name } - pub fn variant_name(&self) -> &String { - &self.variant_name + pub fn variant(&self) -> &Identifier { + &self.variant } pub fn value(&self) -> &Option> { @@ -35,6 +35,6 @@ impl EnumInstance { impl Display for EnumInstance { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}::{}({:?})", self.name, self.variant_name, self.value) + write!(f, "{}::{}({:?})", self.name, self.variant, self.value) } } diff --git a/src/value/list.rs b/src/value/list.rs index 55d48cf..ee15f56 100644 --- a/src/value/list.rs +++ b/src/value/list.rs @@ -1,8 +1,4 @@ -use std::{ - cmp::Ordering, - fmt::{self, Display, Formatter}, - sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, -}; +use std::fmt::{self, Display, Formatter}; use stanza::{ renderer::{console::Console, Renderer}, @@ -12,8 +8,8 @@ use stanza::{ use crate::Value; -#[derive(Debug, Clone)] -pub struct List(Arc>>); +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub struct List(Vec); impl Default for List { fn default() -> Self { @@ -23,23 +19,23 @@ impl Default for List { impl List { pub fn new() -> Self { - List(Arc::new(RwLock::new(Vec::new()))) + List(Vec::new()) } pub fn with_capacity(capacity: usize) -> Self { - List(Arc::new(RwLock::new(Vec::with_capacity(capacity)))) + List(Vec::with_capacity(capacity)) } pub fn with_items(items: Vec) -> Self { - List(Arc::new(RwLock::new(items))) + List(items) } - pub fn items(&self) -> RwLockReadGuard<'_, Vec> { - self.0.read().unwrap() + pub fn items(&self) -> &Vec { + &self.0 } - pub fn items_mut(&self) -> RwLockWriteGuard<'_, Vec> { - self.0.write().unwrap() + pub fn items_mut(&mut self) -> &mut Vec { + &mut self.0 } pub fn as_text_table(&self) -> Table { @@ -73,32 +69,6 @@ impl List { } } -impl Eq for List {} - -impl PartialEq for List { - fn eq(&self, other: &Self) -> bool { - let left = self.0.read().unwrap().clone().into_iter(); - let right = other.0.read().unwrap().clone().into_iter(); - - left.eq(right) - } -} - -impl Ord for List { - fn cmp(&self, other: &Self) -> Ordering { - let left = self.0.read().unwrap().clone().into_iter(); - let right = other.0.read().unwrap().clone().into_iter(); - - left.cmp(right) - } -} - -impl PartialOrd for List { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - impl Display for List { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let renderer = Console::default(); diff --git a/src/value/map.rs b/src/value/map.rs index 9ca6440..95eb727 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -9,7 +9,7 @@ use std::{ fmt::{self, Display, Formatter}, }; -use crate::value::Value; +use crate::{Identifier, Value}; /// A collection dust variables comprised of key-value pairs. /// @@ -17,7 +17,7 @@ use crate::value::Value; /// to one another. #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Map { - inner: BTreeMap, + inner: BTreeMap, } impl Map { @@ -28,19 +28,19 @@ impl Map { } } - pub fn with_values(variables: BTreeMap) -> Self { + pub fn with_values(variables: BTreeMap) -> Self { Map { inner: variables } } - pub fn inner(&self) -> &BTreeMap { + pub fn inner(&self) -> &BTreeMap { &self.inner } - pub fn get(&self, key: &str) -> Option<&Value> { + pub fn get(&self, key: &Identifier) -> Option<&Value> { self.inner.get(key) } - pub fn set(&mut self, key: String, value: Value) { + pub fn set(&mut self, key: Identifier, value: Value) { self.inner.insert(key, value); } @@ -63,7 +63,7 @@ impl Map { vec![key.into(), list.as_text_table().into()], )); } else { - table.push_row([key, &value.to_string()]); + table.push_row([key.to_string(), value.to_string()]); }; } diff --git a/src/value/mod.rs b/src/value/mod.rs index c7bfb1a..c27cea3 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -11,7 +11,6 @@ use serde::{ use std::{ cmp::Ordering, - collections::BTreeMap, convert::TryFrom, fmt::{self, Display, Formatter}, marker::PhantomData, @@ -55,8 +54,8 @@ impl Value { pub fn some(value: Value) -> Value { Value::Enum(EnumInstance::new( - "Option".to_string(), - "Some".to_string(), + Identifier::new("Option"), + Identifier::new("Some"), Some(value), )) } @@ -97,7 +96,7 @@ impl Value { for (key, value) in map.inner() { identifier_types.push(( - Identifier::new(key.clone()), + Identifier::new(key.inner()), TypeSpecification::new(value.r#type()), )); } @@ -828,13 +827,15 @@ impl<'de> Visitor<'de> for ValueVisitor { where M: MapAccess<'de>, { - let mut map = BTreeMap::new(); + let mut map = Map::new(); while let Some((key, value)) = access.next_entry::()? { - map.insert(key, value); + let identifier = Identifier::new(&key); + + map.set(identifier, value); } - Ok(Value::Map(Map::with_values(map))) + Ok(Value::Map(map)) } fn visit_enum(self, data: A) -> std::result::Result diff --git a/src/value/struct_instance.rs b/src/value/struct_instance.rs index 51c666e..e7bc9dc 100644 --- a/src/value/struct_instance.rs +++ b/src/value/struct_instance.rs @@ -2,16 +2,16 @@ use std::fmt::{self, Display, Formatter}; use serde::{ser::SerializeMap, Serialize, Serializer}; -use crate::Map; +use crate::{Identifier, Map}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct StructInstance { - name: String, + name: Identifier, map: Map, } impl StructInstance { - pub fn new(name: String, map: Map) -> Self { + pub fn new(name: Identifier, map: Map) -> Self { StructInstance { name, map } } } diff --git a/tests/value.rs b/tests/value.rs index 626731e..0744fed 100644 --- a/tests/value.rs +++ b/tests/value.rs @@ -138,7 +138,7 @@ fn function() { }; assert_eq!( - &vec![Identifier::new("x".to_string())], + &vec![Identifier::new_or_get("x".to_string())], function.parameters() ); assert_eq!(&Type::Boolean, function.return_type());