1
0

Clean up new API

This commit is contained in:
Jeff 2024-02-15 16:02:27 -05:00
parent c2ba519240
commit ec074177d5
15 changed files with 136 additions and 129 deletions

View File

@ -14,7 +14,7 @@ use crate::{
/// A string by which a variable is known to a context. /// 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 /// 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)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Identifier(Arc<String>); pub struct Identifier(Arc<String>);

View File

@ -62,24 +62,24 @@ impl AbstractTree for Index {
Value::Map(map) => { Value::Map(map) => {
let map = map.inner(); let map = map.inner();
let (identifier, value) = let value = if let IndexExpression::Identifier(identifier) = &self.index {
if let IndexExpression::Identifier(identifier) = &self.index { if let Some(value) = map.get(identifier) {
let value = map.get(identifier).unwrap_or_default(); value
(identifier.clone(), value)
} else { } else {
let index_value = self.index.run(source, context)?; return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone()));
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))
} else { } 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) => { Value::String(string) => {
let index = self.index.run(source, context)?.as_integer()? as usize; let index = self.index.run(source, context)?.as_integer()? as usize;

View File

@ -203,7 +203,7 @@ impl Callable for StrFunction {
&self, &self,
arguments: &[Value], arguments: &[Value],
_source: &str, _source: &str,
context: &Context, _context: &Context,
) -> Result<Value, RuntimeError> { ) -> Result<Value, RuntimeError> {
let value = match self { let value = match self {
StrFunction::AsBytes => { StrFunction::AsBytes => {
@ -335,8 +335,8 @@ impl Callable for StrFunction {
let mut string = arguments.first().unwrap().as_string()?.clone(); let mut string = arguments.first().unwrap().as_string()?.clone();
let range = arguments.get(1).unwrap().as_list()?.items(); let range = arguments.get(1).unwrap().as_list()?.items();
let start = range.first().unwrap_or_default().as_integer()? as usize; let start = range[0].as_integer()? as usize;
let end = range.get(1).unwrap_or_default().as_integer()? as usize; let end = range[1].as_integer()? as usize;
let pattern = arguments.get(2).unwrap().as_string()?; let pattern = arguments.get(2).unwrap().as_string()?;
string.replace_range(start..end, pattern); string.replace_range(start..end, pattern);

View File

@ -18,12 +18,10 @@ pub enum BuiltInIdentifier {
} }
impl BuiltInIdentifier { impl BuiltInIdentifier {
pub fn get(&self) -> &Identifier { pub fn get(&self) -> Identifier {
match self { match self {
BuiltInIdentifier::Option => { BuiltInIdentifier::Option => OPTION.get_or_init(|| Identifier::new("Option")).clone(),
return OPTION.get_or_init(|| Identifier::new("Option")); BuiltInIdentifier::None => NONE.get_or_init(|| Identifier::new("None")).clone(),
}
BuiltInIdentifier::None => return NONE.get_or_init(|| Identifier::new("None")),
} }
} }
} }

View File

@ -28,7 +28,7 @@ impl BuiltInTypeDefinition {
} }
} }
pub fn get(&self, context: &Context) -> &Result<TypeDefinition, RwLockError> { pub fn get(&self, _context: &Context) -> &Result<TypeDefinition, RwLockError> {
match self { match self {
BuiltInTypeDefinition::Option => OPTION.get_or_init(|| { BuiltInTypeDefinition::Option => OPTION.get_or_init(|| {
let definition = TypeDefinition::Enum(EnumDefinition::new( let definition = TypeDefinition::Enum(EnumDefinition::new(

View File

@ -86,80 +86,95 @@ impl BuiltInValue {
/// Returns the value by creating it or, if it has already been accessed, retrieving it from its /// Returns the value by creating it or, if it has already been accessed, retrieving it from its
/// [OnceLock][]. /// [OnceLock][].
pub fn get(&self) -> &Value { pub fn get(&self) -> Value {
match self { match self {
BuiltInValue::Args => ARGS.get_or_init(|| { BuiltInValue::Args => ARGS
let args = args().map(|arg| Value::string(arg.to_string())).collect(); .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 => { BuiltInValue::AssertEqual => {
&Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual)) Value::Function(Function::BuiltIn(BuiltInFunction::AssertEqual))
} }
BuiltInValue::Fs => FS.get_or_init(|| { BuiltInValue::Fs => FS
let mut fs_map = Map::new(); .get_or_init(|| {
let mut fs_map = Map::new();
for fs_function in fs_functions() { for fs_function in fs_functions() {
let key = fs_function.name(); let key = fs_function.name();
let value = let value =
Value::Function(Function::BuiltIn(BuiltInFunction::Fs(fs_function))); 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) Value::Map(fs_map)
}), })
BuiltInValue::Json => JSON.get_or_init(|| { .clone(),
let mut json_map = Map::new(); BuiltInValue::Json => JSON
.get_or_init(|| {
let mut json_map = Map::new();
for json_function in json_functions() { for json_function in json_functions() {
let key = json_function.name(); let key = json_function.name();
let value = let value = Value::Function(Function::BuiltIn(BuiltInFunction::Json(
Value::Function(Function::BuiltIn(BuiltInFunction::Json(json_function))); json_function,
)));
json_map.set(Identifier::new(key), value); json_map.set(Identifier::new(key), value);
} }
Value::Map(json_map) Value::Map(json_map)
}), })
BuiltInValue::Length => &Value::Function(Function::BuiltIn(BuiltInFunction::Length)), .clone(),
BuiltInValue::None => &Value::Enum(EnumInstance::new( BuiltInValue::Length => Value::Function(Function::BuiltIn(BuiltInFunction::Length)),
Identifier::new("Option"), BuiltInValue::None => NONE
Identifier::new("None"), .get_or_init(|| {
None, Value::Enum(EnumInstance::new(
)), Identifier::new("Option"),
BuiltInValue::Output => &Value::Function(Function::BuiltIn(BuiltInFunction::Output)), Identifier::new("None"),
BuiltInValue::Random => RANDOM.get_or_init(|| { None,
let mut random_map = Map::new(); ))
})
.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 [ for built_in_function in [
BuiltInFunction::RandomBoolean, BuiltInFunction::RandomBoolean,
BuiltInFunction::RandomFloat, BuiltInFunction::RandomFloat,
BuiltInFunction::RandomFrom, BuiltInFunction::RandomFrom,
BuiltInFunction::RandomInteger, BuiltInFunction::RandomInteger,
] { ] {
let identifier = Identifier::new(built_in_function.name()); let identifier = Identifier::new(built_in_function.name());
let value = Value::Function(Function::BuiltIn(built_in_function)); let value = Value::Function(Function::BuiltIn(built_in_function));
random_map.set(identifier, value); random_map.set(identifier, value);
} }
Value::Map(random_map) Value::Map(random_map)
}), })
BuiltInValue::Str => STR.get_or_init(|| { .clone(),
let mut str_map = Map::new(); BuiltInValue::Str => STR
.get_or_init(|| {
let mut str_map = Map::new();
for string_function in string_functions() { for string_function in string_functions() {
let identifier = Identifier::new(string_function.name()); let identifier = Identifier::new(string_function.name());
let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( let value = Value::Function(Function::BuiltIn(BuiltInFunction::String(
string_function, string_function,
))); )));
str_map.set(identifier, value); str_map.set(identifier, value);
} }
Value::Map(str_map) Value::Map(str_map)
}), })
.clone(),
} }
} }
} }

View File

@ -11,7 +11,7 @@ use reedline::{
use std::{borrow::Cow, fs::read_to_string, path::PathBuf, process::Command}; use std::{borrow::Cow, fs::read_to_string, path::PathBuf, process::Command};
use dust_lang::{ 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. /// Command-line arguments to be parsed.
@ -55,7 +55,7 @@ fn main() {
if let Some(input) = args.input { if let Some(input) = args.input {
context context
.set_value("input".to_string(), Value::string(input)) .set_value(Identifier::new("input"), Value::string(input))
.unwrap(); .unwrap();
} }
@ -63,7 +63,7 @@ fn main() {
let file_contents = read_to_string(path).unwrap(); let file_contents = read_to_string(path).unwrap();
context context
.set_value("input".to_string(), Value::string(file_contents)) .set_value(Identifier::new("input"), Value::string(file_contents))
.unwrap(); .unwrap();
} }

View File

@ -250,12 +250,6 @@ impl Default for Value {
} }
} }
impl Default for &Value {
fn default() -> Self {
BuiltInValue::None.get()
}
}
impl Add for Value { impl Add for Value {
type Output = Result<Value, RuntimeError>; type Output = Result<Value, RuntimeError>;

View File

@ -5,8 +5,8 @@ fn option() {
assert_eq!( assert_eq!(
interpret("Option::None"), interpret("Option::None"),
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(
"Option".to_string(), Identifier::new("Option"),
"None".to_string(), Identifier::new("None"),
Some(Value::none()), Some(Value::none()),
))) )))
); );
@ -19,8 +19,8 @@ fn option() {
" "
), ),
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(
"Option".to_string(), Identifier::new("Option"),
"Some".to_string(), Identifier::new("None"),
Some(Value::Integer(1)), Some(Value::Integer(1)),
))) )))
); );
@ -31,8 +31,8 @@ fn result() {
assert_eq!( assert_eq!(
interpret("Result::Ok(1)"), interpret("Result::Ok(1)"),
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(
"Result".to_string(), Identifier::new("Result"),
"Ok".to_string(), Identifier::new("Ok"),
Some(Value::Integer(1)), Some(Value::Integer(1)),
))) )))
); );
@ -44,8 +44,8 @@ fn result() {
" "
), ),
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(
"Result".to_string(), Identifier::new("Result"),
"Error".to_string(), Identifier::new("Error"),
Some(Value::String("uh-oh!".to_string())), Some(Value::String("uh-oh!".to_string())),
))) )))
); );

View File

@ -16,16 +16,16 @@ fn assert_equal() {
assert_eq!( assert_eq!(
interpret("assert_equal(false, false)"), interpret("assert_equal(false, false)"),
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(
"Result".to_string(), Identifier::new("Result"),
"Ok".to_string(), Identifier::new("Ok"),
Some(Value::none()), Some(Value::none()),
))) )))
); );
assert_eq!( assert_eq!(
interpret("assert_equal(true, false)"), interpret("assert_equal(true, false)"),
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(
"Result".to_string(), Identifier::new("Result"),
"Error".to_string(), Identifier::new("Error"),
Some(Value::none()), Some(Value::none()),
))) )))
); );

View File

@ -16,8 +16,8 @@ fn simple_enum() {
assert_eq!( assert_eq!(
result, result,
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(
"Foobar".to_string(), Identifier::new("Foobar"),
"Foo".to_string(), Identifier::new("Foo"),
Some(Value::none()) Some(Value::none())
))) )))
); );
@ -43,11 +43,11 @@ fn nested_enum() {
assert_eq!( assert_eq!(
result, result,
Ok(Value::Enum(EnumInstance::new( Ok(Value::Enum(EnumInstance::new(
"Foobar".to_string(), Identifier::new("Foobar"),
"Bar".to_string(), Identifier::new("Bar"),
Some(Value::Enum(EnumInstance::new( Some(Value::Enum(EnumInstance::new(
"Fizzbuzz".to_string(), Identifier::new("Fizzbuzz"),
"Fizz".to_string(), Identifier::new("Fizz"),
Some(Value::none()) Some(Value::none())
))) )))
))) )))

View File

@ -67,8 +67,8 @@ fn modify_map() {
let mut map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1)); map.set(Identifier::new("x"), Value::Integer(1));
map.set("y".to_string(), Value::Integer(2)); map.set(Identifier::new("y"), Value::Integer(2));
assert_eq!(Ok(Value::Map(map)), result); assert_eq!(Ok(Value::Map(map)), result);
} }

View File

@ -57,7 +57,7 @@ fn function_context_does_not_capture_normal_values() {
" "
), ),
Err(Error::Validation( 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() { fn function_context_captures_structure_definitions() {
let mut map = Map::new(); let mut map = Map::new();
map.set("name".to_string(), Value::string("bob")); map.set(Identifier::new("name"), Value::string("bob"));
assert_eq!( assert_eq!(
interpret( interpret(

View File

@ -17,10 +17,13 @@ fn simple_struct() {
let mut map = Map::new(); let mut map = Map::new();
map.set("bar".to_string(), Value::Integer(0)); map.set(Identifier::new("bar"), Value::Integer(0));
map.set("baz".to_string(), Value::String("hiya".to_string())); 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); assert_eq!(result, expected);
} }
@ -42,12 +45,12 @@ fn nested_struct() {
let mut foo_map = Map::new(); let mut foo_map = Map::new();
foo_map.set( foo_map.set(
"bar".to_string(), Identifier::new("bar"),
Value::Struct(StructInstance::new("Bar".to_string(), Map::new())), Value::Struct(StructInstance::new(Identifier::new("Bar"), Map::new())),
); );
let expected = Ok(Value::Struct(StructInstance::new( let expected = Ok(Value::Struct(StructInstance::new(
"Foo".to_string(), Identifier::new("Foo"),
foo_map, foo_map,
))); )));

View File

@ -71,8 +71,8 @@ fn empty_list() {
fn map() { fn map() {
let mut map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1)); map.set(Identifier::new("x"), Value::Integer(1));
map.set("foo".to_string(), Value::string("bar".to_string())); map.set(Identifier::new("foo"), Value::string("bar".to_string()));
assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map))); assert_eq!(interpret("{ x = 1, foo = 'bar' }"), Ok(Value::Map(map)));
} }
@ -86,8 +86,8 @@ fn empty_map() {
fn map_types() { fn map_types() {
let mut map = Map::new(); let mut map = Map::new();
map.set("x".to_string(), Value::Integer(1)); map.set(Identifier::new("x"), Value::Integer(1));
map.set("foo".to_string(), Value::string("bar".to_string())); map.set(Identifier::new("foo"), Value::string("bar".to_string()));
assert_eq!( assert_eq!(
interpret("{ x <int> = 1, foo <str> = 'bar' }"), interpret("{ x <int> = 1, foo <str> = 'bar' }"),
@ -137,10 +137,7 @@ fn function() {
panic!("Something is wrong with this test..."); panic!("Something is wrong with this test...");
}; };
assert_eq!( assert_eq!(&vec![Identifier::new("x")], function.parameters());
&vec![Identifier::new_or_get("x".to_string())],
function.parameters()
);
assert_eq!(&Type::Boolean, function.return_type()); assert_eq!(&Type::Boolean, function.return_type());
} }