diff --git a/src/abstract_tree/built_in_value.rs b/src/abstract_tree/built_in_value.rs index cc5f66d..169e702 100644 --- a/src/abstract_tree/built_in_value.rs +++ b/src/abstract_tree/built_in_value.rs @@ -103,8 +103,8 @@ impl BuiltInValue { BuiltInFunction::RandomInteger, ] { let key = built_in_function.name().to_string(); - let r#type = built_in_function.r#type(); let value = Value::Function(Function::BuiltIn(built_in_function)); + let r#type = built_in_function.r#type(); random_context.insert(key, (value, r#type)); } diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index c926c52..2ecd926 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -68,36 +68,19 @@ impl AbstractTree for FunctionCall { } }; - let required_argument_count = - parameter_types.iter().fold( - 0, - |acc, r#type| { - if r#type.is_option() { - acc - } else { - acc + 1 - } - }, - ); - - if self.arguments.len() < required_argument_count { - return Err(Error::ExpectedFunctionArgumentMinimum { - minumum: required_argument_count, + if self.arguments.len() != parameter_types.len() { + return Err(Error::ExpectedFunctionArgumentAmount { + expected: parameter_types.len(), actual: self.arguments.len(), - }); + } + .at_source_position(source, self.syntax_position)); } for (index, expression) in self.arguments.iter().enumerate() { if let Some(r#type) = parameter_types.get(index) { - let expected_type = expression.expected_type(context)?; - - if let Type::Option(optional_type) = r#type { - optional_type.check(&expected_type)?; - } else { - r#type - .check(&expression.expected_type(context)?) - .map_err(|error| error.at_source_position(source, self.syntax_position))?; - } + r#type + .check(&expression.expected_type(context)?) + .map_err(|error| error.at_source_position(source, self.syntax_position))?; } } diff --git a/src/abstract_tree/type.rs b/src/abstract_tree/type.rs index ef4793e..eaf9618 100644 --- a/src/abstract_tree/type.rs +++ b/src/abstract_tree/type.rs @@ -150,10 +150,6 @@ impl Type { pub fn is_map(&self) -> bool { matches!(self, Type::Map(_)) } - - pub fn is_option(&self) -> bool { - matches!(self, Type::Option(_)) - } } impl AbstractTree for Type { diff --git a/src/built_in_functions/mod.rs b/src/built_in_functions/mod.rs index a8d9afc..1699a1e 100644 --- a/src/built_in_functions/mod.rs +++ b/src/built_in_functions/mod.rs @@ -3,7 +3,6 @@ mod string; use std::{ fmt::{self, Display, Formatter}, fs::read_to_string, - process::Command, }; use rand::{random, thread_rng, Rng}; @@ -13,10 +12,9 @@ use crate::{Error, Format, Map, Result, Type, Value}; pub use string::{string_functions, StringFunction}; -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub enum BuiltInFunction { AssertEqual, - Binary(String), FsRead, JsonParse, Length, @@ -32,7 +30,6 @@ impl BuiltInFunction { pub fn name(&self) -> &'static str { match self { BuiltInFunction::AssertEqual => "assert_equal", - BuiltInFunction::Binary(_) => "binary", BuiltInFunction::FsRead => "read", BuiltInFunction::JsonParse => "parse", BuiltInFunction::Length => "length", @@ -48,10 +45,6 @@ impl BuiltInFunction { pub fn r#type(&self) -> Type { match self { BuiltInFunction::AssertEqual => Type::function(vec![Type::Any, Type::Any], Type::None), - BuiltInFunction::Binary(_) => Type::function( - vec![Type::Option(Box::new(Type::String))], - Type::Option(Box::new(Type::Integer)), - ), BuiltInFunction::FsRead => Type::function(vec![Type::String], Type::String), BuiltInFunction::JsonParse => Type::function(vec![Type::String], Type::Any), BuiltInFunction::Length => Type::function(vec![Type::Collection], Type::Integer), @@ -74,36 +67,6 @@ impl BuiltInFunction { Ok(Value::Boolean(left == right)) } - BuiltInFunction::Binary(binary_name) => { - let input = if let Some(value) = arguments.first() { - value.clone() - } else { - Value::none() - }; - let mut command = Command::new(binary_name); - - if let Ok(Some(value)) = input.as_option() { - let input_string = value.as_string()?; - - if !input_string.is_empty() { - command.args(input_string.split_whitespace()); - } - } - - if let Ok(input_string) = input.as_string() { - if !input_string.is_empty() { - command.args(input_string.split_whitespace()); - } - } - - let output = command.spawn()?.wait()?; - let status_code = match output.code() { - Some(code) => Value::some(Value::Integer(code as i64)), - None => Value::none(), - }; - - Ok(status_code) - } BuiltInFunction::FsRead => { Error::expect_argument_amount(self.name(), 1, arguments.len())?; diff --git a/src/error.rs b/src/error.rs index 986e03c..3c85f26 100644 --- a/src/error.rs +++ b/src/error.rs @@ -83,7 +83,8 @@ pub enum Error { /// A function was called with the wrong amount of arguments. ExpectedFunctionArgumentMinimum { - minumum: usize, + source: String, + minumum_expected: usize, actual: usize, }, @@ -337,10 +338,14 @@ impl fmt::Display for Error { ExpectedFunctionArgumentAmount { expected, actual } => { write!(f, "Expected {expected} arguments, but got {actual}.",) } - ExpectedFunctionArgumentMinimum { minumum, actual } => { + ExpectedFunctionArgumentMinimum { + source, + minumum_expected, + actual, + } => { write!( f, - "Expected at least {minumum} arguments, but got {actual}." + "{source} expected at least {minumum_expected} arguments, but got {actual}." ) } ExpectedString { actual } => { diff --git a/src/main.rs b/src/main.rs index f7403cb..e66cb81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use reedline::{ use std::{fs::read_to_string, path::PathBuf}; -use dust_lang::{built_in_values, Function, Interpreter, Map, Result, Value}; +use dust_lang::{built_in_values, Interpreter, Map, Result, Value}; /// Command-line arguments to be parsed. #[derive(Parser, Debug)] @@ -171,31 +171,6 @@ impl Highlighter for DustHighlighter { } fn run_shell(context: Map) -> Result<()> { - for (key, value) in std::env::vars() { - if key == "PATH" { - for path in value.split([' ', ':']) { - let path_dir = if let Ok(path_dir) = PathBuf::from(path).read_dir() { - path_dir - } else { - continue; - }; - - for entry in path_dir { - let entry = entry?; - - if entry.file_type()?.is_file() { - context.set( - entry.file_name().to_string_lossy().to_string(), - Value::Function(Function::BuiltIn(dust_lang::BuiltInFunction::Binary( - entry.file_name().to_string_lossy().to_string(), - ))), - )?; - } - } - } - } - } - let mut interpreter = Interpreter::new(context.clone()); let prompt = DefaultPrompt::default(); let mut keybindings = default_emacs_keybindings();