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.
///
/// 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<String>);

View File

@ -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;

View File

@ -203,7 +203,7 @@ impl Callable for StrFunction {
&self,
arguments: &[Value],
_source: &str,
context: &Context,
_context: &Context,
) -> Result<Value, RuntimeError> {
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);

View File

@ -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(),
}
}
}

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 {
BuiltInTypeDefinition::Option => OPTION.get_or_init(|| {
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
/// [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(),
}
}
}

View File

@ -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();
}

View File

@ -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<Value, RuntimeError>;

View File

@ -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())),
)))
);

View File

@ -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()),
)))
);

View File

@ -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())
)))
)))

View File

@ -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);
}

View File

@ -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(

View File

@ -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,
)));

View File

@ -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 <int> = 1, foo <str> = '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());
}