From ec074177d5bb6ec576c0e6983a1fe4c5ff9b9e4f Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 15 Feb 2024 16:02:27 -0500 Subject: [PATCH] Clean up new API --- src/abstract_tree/identifier.rs | 2 +- src/abstract_tree/index.rs | 32 +++---- src/built_in_functions/str.rs | 6 +- src/built_in_identifiers.rs | 8 +- src/built_in_type_definitions.rs | 2 +- src/built_in_values.rs | 131 ++++++++++++++++------------- src/main.rs | 6 +- src/value/mod.rs | 6 -- tests/built_in_type_definitions.rs | 16 ++-- tests/built_in_values.rs | 8 +- tests/enums.rs | 12 +-- tests/for_loop.rs | 4 +- tests/functions.rs | 4 +- tests/structs.rs | 15 ++-- tests/value.rs | 13 ++- 15 files changed, 136 insertions(+), 129 deletions(-) diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index 7cbf681..e0edd0c 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -14,7 +14,7 @@ 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 and can be used to retrieve a Value instance from a Map or Context. +/// pair. Its inner value can be used to retrieve a Value instance from a Map. #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct Identifier(Arc); diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index f59df4b..c0a4cea 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -62,24 +62,24 @@ impl AbstractTree for Index { Value::Map(map) => { let map = map.inner(); - let (identifier, value) = - if let IndexExpression::Identifier(identifier) = &self.index { - let value = map.get(identifier).unwrap_or_default(); - - (identifier.clone(), value) + let value = if let IndexExpression::Identifier(identifier) = &self.index { + if let Some(value) = map.get(identifier) { + 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(); - - (identifier, value) - }; - - if value.is_none() { - Err(RuntimeError::VariableIdentifierNotFound(identifier)) + return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); + } } else { - Ok(value.clone()) - } + let index_value = self.index.run(source, context)?; + let identifier = Identifier::new(index_value.as_string()?); + + if let Some(value) = map.get(&identifier) { + value + } else { + return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); + } + }; + + Ok(value.clone()) } Value::String(string) => { let index = self.index.run(source, context)?.as_integer()? as usize; diff --git a/src/built_in_functions/str.rs b/src/built_in_functions/str.rs index 331e9da..08d215a 100644 --- a/src/built_in_functions/str.rs +++ b/src/built_in_functions/str.rs @@ -203,7 +203,7 @@ impl Callable for StrFunction { &self, arguments: &[Value], _source: &str, - context: &Context, + _context: &Context, ) -> Result { let value = match self { StrFunction::AsBytes => { @@ -335,8 +335,8 @@ impl Callable for StrFunction { let mut string = arguments.first().unwrap().as_string()?.clone(); let range = arguments.get(1).unwrap().as_list()?.items(); - let start = range.first().unwrap_or_default().as_integer()? as usize; - let end = range.get(1).unwrap_or_default().as_integer()? as usize; + let start = range[0].as_integer()? as usize; + let end = range[1].as_integer()? as usize; let pattern = arguments.get(2).unwrap().as_string()?; string.replace_range(start..end, pattern); diff --git a/src/built_in_identifiers.rs b/src/built_in_identifiers.rs index 7c6918f..c25b4b2 100644 --- a/src/built_in_identifiers.rs +++ b/src/built_in_identifiers.rs @@ -18,12 +18,10 @@ pub enum BuiltInIdentifier { } impl BuiltInIdentifier { - pub fn get(&self) -> &Identifier { + 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")), + BuiltInIdentifier::Option => OPTION.get_or_init(|| Identifier::new("Option")).clone(), + BuiltInIdentifier::None => NONE.get_or_init(|| Identifier::new("None")).clone(), } } } diff --git a/src/built_in_type_definitions.rs b/src/built_in_type_definitions.rs index e3cab3d..d52bf7f 100644 --- a/src/built_in_type_definitions.rs +++ b/src/built_in_type_definitions.rs @@ -28,7 +28,7 @@ impl BuiltInTypeDefinition { } } - pub fn get(&self, context: &Context) -> &Result { + pub fn get(&self, _context: &Context) -> &Result { match self { BuiltInTypeDefinition::Option => OPTION.get_or_init(|| { let definition = TypeDefinition::Enum(EnumDefinition::new( diff --git a/src/built_in_values.rs b/src/built_in_values.rs index 2e293b9..3e84733 100644 --- a/src/built_in_values.rs +++ b/src/built_in_values.rs @@ -86,80 +86,95 @@ impl BuiltInValue { /// Returns the value by creating it or, if it has already been accessed, retrieving it from its /// [OnceLock][]. - pub fn get(&self) -> &Value { + pub fn get(&self) -> Value { match self { - BuiltInValue::Args => ARGS.get_or_init(|| { - let args = args().map(|arg| Value::string(arg.to_string())).collect(); + BuiltInValue::Args => ARGS + .get_or_init(|| { + let args = args().map(|arg| Value::string(arg.to_string())).collect(); - Value::List(List::with_items(args)) - }), + Value::List(List::with_items(args)) + }) + .clone(), BuiltInValue::AssertEqual => { - &Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual)) + Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual)) } - BuiltInValue::Fs => FS.get_or_init(|| { - let mut fs_map = Map::new(); + BuiltInValue::Fs => FS + .get_or_init(|| { + let mut fs_map = Map::new(); - for fs_function in fs_functions() { - let key = fs_function.name(); - let value = - Value::Function(Function::BuiltIn(BuiltInFunction::Fs(fs_function))); + for fs_function in fs_functions() { + let key = fs_function.name(); + let value = + Value::Function(Function::BuiltIn(BuiltInFunction::Fs(fs_function))); - fs_map.set(Identifier::new(key), value); - } + fs_map.set(Identifier::new(key), value); + } - Value::Map(fs_map) - }), - BuiltInValue::Json => JSON.get_or_init(|| { - let mut json_map = Map::new(); + Value::Map(fs_map) + }) + .clone(), + BuiltInValue::Json => JSON + .get_or_init(|| { + let mut json_map = Map::new(); - for json_function in json_functions() { - let key = json_function.name(); - let value = - Value::Function(Function::BuiltIn(BuiltInFunction::Json(json_function))); + for json_function in json_functions() { + let key = json_function.name(); + let value = Value::Function(Function::BuiltIn(BuiltInFunction::Json( + json_function, + ))); - json_map.set(Identifier::new(key), value); - } + json_map.set(Identifier::new(key), value); + } - Value::Map(json_map) - }), - BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)), - 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_map = Map::new(); + Value::Map(json_map) + }) + .clone(), + BuiltInValue::Length => Value::Function(Function::BuiltIn(BuiltInFunction::Length)), + BuiltInValue::None => NONE + .get_or_init(|| { + Value::Enum(EnumInstance::new( + Identifier::new("Option"), + Identifier::new("None"), + None, + )) + }) + .clone(), + BuiltInValue::Output => Value::Function(Function::BuiltIn(BuiltInFunction::Output)), + BuiltInValue::Random => RANDOM + .get_or_init(|| { + let mut random_map = Map::new(); - for built_in_function in [ - BuiltInFunction::RandomBoolean, - BuiltInFunction::RandomFloat, - BuiltInFunction::RandomFrom, - BuiltInFunction::RandomInteger, - ] { - let identifier = Identifier::new(built_in_function.name()); - let value = Value::Function(Function::BuiltIn(built_in_function)); + for built_in_function in [ + BuiltInFunction::RandomBoolean, + BuiltInFunction::RandomFloat, + BuiltInFunction::RandomFrom, + BuiltInFunction::RandomInteger, + ] { + let identifier = Identifier::new(built_in_function.name()); + let value = Value::Function(Function::BuiltIn(built_in_function)); - random_map.set(identifier, value); - } + random_map.set(identifier, value); + } - Value::Map(random_map) - }), - BuiltInValue::Str => STR.get_or_init(|| { - let mut str_map = Map::new(); + Value::Map(random_map) + }) + .clone(), + BuiltInValue::Str => STR + .get_or_init(|| { + let mut str_map = Map::new(); - for string_function in string_functions() { - let identifier = Identifier::new(string_function.name()); - let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( - string_function, - ))); + for string_function in string_functions() { + let identifier = Identifier::new(string_function.name()); + let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( + string_function, + ))); - str_map.set(identifier, value); - } + str_map.set(identifier, value); + } - Value::Map(str_map) - }), + Value::Map(str_map) + }) + .clone(), } } } diff --git a/src/main.rs b/src/main.rs index 0329543..35ad447 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use reedline::{ use std::{borrow::Cow, fs::read_to_string, path::PathBuf, process::Command}; use dust_lang::{ - built_in_values::all_built_in_values, Context, Error, Interpreter, Value, ValueData, + built_in_values::all_built_in_values, Context, Error, Identifier, Interpreter, Value, ValueData, }; /// Command-line arguments to be parsed. @@ -55,7 +55,7 @@ fn main() { if let Some(input) = args.input { context - .set_value("input".to_string(), Value::string(input)) + .set_value(Identifier::new("input"), Value::string(input)) .unwrap(); } @@ -63,7 +63,7 @@ fn main() { let file_contents = read_to_string(path).unwrap(); context - .set_value("input".to_string(), Value::string(file_contents)) + .set_value(Identifier::new("input"), Value::string(file_contents)) .unwrap(); } diff --git a/src/value/mod.rs b/src/value/mod.rs index c27cea3..2b256dd 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -250,12 +250,6 @@ impl Default for Value { } } -impl Default for &Value { - fn default() -> Self { - BuiltInValue::None.get() - } -} - impl Add for Value { type Output = Result; diff --git a/tests/built_in_type_definitions.rs b/tests/built_in_type_definitions.rs index c4c7f62..c91a70b 100644 --- a/tests/built_in_type_definitions.rs +++ b/tests/built_in_type_definitions.rs @@ -5,8 +5,8 @@ fn option() { assert_eq!( interpret("Option::None"), Ok(Value::Enum(EnumInstance::new( - "Option".to_string(), - "None".to_string(), + Identifier::new("Option"), + Identifier::new("None"), Some(Value::none()), ))) ); @@ -19,8 +19,8 @@ fn option() { " ), Ok(Value::Enum(EnumInstance::new( - "Option".to_string(), - "Some".to_string(), + Identifier::new("Option"), + Identifier::new("None"), Some(Value::Integer(1)), ))) ); @@ -31,8 +31,8 @@ fn result() { assert_eq!( interpret("Result::Ok(1)"), Ok(Value::Enum(EnumInstance::new( - "Result".to_string(), - "Ok".to_string(), + Identifier::new("Result"), + Identifier::new("Ok"), Some(Value::Integer(1)), ))) ); @@ -44,8 +44,8 @@ fn result() { " ), Ok(Value::Enum(EnumInstance::new( - "Result".to_string(), - "Error".to_string(), + Identifier::new("Result"), + Identifier::new("Error"), Some(Value::String("uh-oh!".to_string())), ))) ); diff --git a/tests/built_in_values.rs b/tests/built_in_values.rs index 54a87b0..a925d30 100644 --- a/tests/built_in_values.rs +++ b/tests/built_in_values.rs @@ -16,16 +16,16 @@ fn assert_equal() { assert_eq!( interpret("assert_equal(false, false)"), Ok(Value::Enum(EnumInstance::new( - "Result".to_string(), - "Ok".to_string(), + Identifier::new("Result"), + Identifier::new("Ok"), Some(Value::none()), ))) ); assert_eq!( interpret("assert_equal(true, false)"), Ok(Value::Enum(EnumInstance::new( - "Result".to_string(), - "Error".to_string(), + Identifier::new("Result"), + Identifier::new("Error"), Some(Value::none()), ))) ); diff --git a/tests/enums.rs b/tests/enums.rs index 29e149e..93e7f33 100644 --- a/tests/enums.rs +++ b/tests/enums.rs @@ -16,8 +16,8 @@ fn simple_enum() { assert_eq!( result, Ok(Value::Enum(EnumInstance::new( - "Foobar".to_string(), - "Foo".to_string(), + Identifier::new("Foobar"), + Identifier::new("Foo"), Some(Value::none()) ))) ); @@ -43,11 +43,11 @@ fn nested_enum() { assert_eq!( result, Ok(Value::Enum(EnumInstance::new( - "Foobar".to_string(), - "Bar".to_string(), + Identifier::new("Foobar"), + Identifier::new("Bar"), Some(Value::Enum(EnumInstance::new( - "Fizzbuzz".to_string(), - "Fizz".to_string(), + Identifier::new("Fizzbuzz"), + Identifier::new("Fizz"), Some(Value::none()) ))) ))) diff --git a/tests/for_loop.rs b/tests/for_loop.rs index f573c64..dbe200f 100644 --- a/tests/for_loop.rs +++ b/tests/for_loop.rs @@ -67,8 +67,8 @@ fn modify_map() { let mut map = Map::new(); - map.set("x".to_string(), Value::Integer(1)); - map.set("y".to_string(), Value::Integer(2)); + map.set(Identifier::new("x"), Value::Integer(1)); + map.set(Identifier::new("y"), Value::Integer(2)); assert_eq!(Ok(Value::Map(map)), result); } diff --git a/tests/functions.rs b/tests/functions.rs index 4df92cc..3befcf6 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -57,7 +57,7 @@ fn function_context_does_not_capture_normal_values() { " ), Err(Error::Validation( - ValidationError::VariableIdentifierNotFound(Identifier::new("x".to_string())) + ValidationError::VariableIdentifierNotFound(Identifier::new("x")) )) ); @@ -91,7 +91,7 @@ fn function_context_captures_functions() { fn function_context_captures_structure_definitions() { let mut map = Map::new(); - map.set("name".to_string(), Value::string("bob")); + map.set(Identifier::new("name"), Value::string("bob")); assert_eq!( interpret( diff --git a/tests/structs.rs b/tests/structs.rs index d8ad360..0829578 100644 --- a/tests/structs.rs +++ b/tests/structs.rs @@ -17,10 +17,13 @@ fn simple_struct() { let mut map = Map::new(); - map.set("bar".to_string(), Value::Integer(0)); - map.set("baz".to_string(), Value::String("hiya".to_string())); + map.set(Identifier::new("bar"), Value::Integer(0)); + map.set(Identifier::new("baz"), Value::String("hiya".to_string())); - let expected = Ok(Value::Struct(StructInstance::new("Foo".to_string(), map))); + let expected = Ok(Value::Struct(StructInstance::new( + Identifier::new("Foo"), + map, + ))); assert_eq!(result, expected); } @@ -42,12 +45,12 @@ fn nested_struct() { let mut foo_map = Map::new(); foo_map.set( - "bar".to_string(), - Value::Struct(StructInstance::new("Bar".to_string(), Map::new())), + Identifier::new("bar"), + Value::Struct(StructInstance::new(Identifier::new("Bar"), Map::new())), ); let expected = Ok(Value::Struct(StructInstance::new( - "Foo".to_string(), + Identifier::new("Foo"), foo_map, ))); diff --git a/tests/value.rs b/tests/value.rs index 0744fed..9906e96 100644 --- a/tests/value.rs +++ b/tests/value.rs @@ -71,8 +71,8 @@ fn empty_list() { fn map() { let mut map = Map::new(); - map.set("x".to_string(), Value::Integer(1)); - map.set("foo".to_string(), Value::string("bar".to_string())); + map.set(Identifier::new("x"), Value::Integer(1)); + map.set(Identifier::new("foo"), Value::string("bar".to_string())); assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map))); } @@ -86,8 +86,8 @@ fn empty_map() { fn map_types() { let mut map = Map::new(); - map.set("x".to_string(), Value::Integer(1)); - map.set("foo".to_string(), Value::string("bar".to_string())); + map.set(Identifier::new("x"), Value::Integer(1)); + map.set(Identifier::new("foo"), Value::string("bar".to_string())); assert_eq!( interpret("{ x = 1, foo = 'bar' }"), @@ -137,10 +137,7 @@ fn function() { panic!("Something is wrong with this test..."); }; - assert_eq!( - &vec![Identifier::new_or_get("x".to_string())], - function.parameters() - ); + assert_eq!(&vec![Identifier::new("x")], function.parameters()); assert_eq!(&Type::Boolean, function.return_type()); }