diff --git a/src/assignment_evaluator.rs b/src/assignment_evaluator.rs index 70a5b5c..9ab50cd 100644 --- a/src/assignment_evaluator.rs +++ b/src/assignment_evaluator.rs @@ -116,7 +116,7 @@ impl<'a, 'b> AssignmentEvaluator<'a, 'b> { invocation_directory: &self.invocation_directory, dotenv: self.dotenv, }; - evaluate_function(token, name, &context, &call_arguments) + Function::evaluate(token, name, &context, &call_arguments) } Expression::String { ref cooked_string } => Ok(cooked_string.cooked.to_string()), Expression::Backtick { raw, ref token } => { diff --git a/src/assignment_resolver.rs b/src/assignment_resolver.rs index ea10aab..f37029b 100644 --- a/src/assignment_resolver.rs +++ b/src/assignment_resolver.rs @@ -77,7 +77,7 @@ impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> { ref token, ref arguments, .. - } => resolve_function(token, arguments.len())?, + } => Function::resolve(token, arguments.len())?, Expression::Concatination { ref lhs, ref rhs } => { self.resolve_expression(lhs)?; self.resolve_expression(rhs)?; diff --git a/src/common.rs b/src/common.rs index 6d43494..a3b27dd 100644 --- a/src/common.rs +++ b/src/common.rs @@ -26,11 +26,12 @@ pub(crate) use crate::{ assignment_evaluator::AssignmentEvaluator, assignment_resolver::AssignmentResolver, color::Color, - compilation_error::{CompilationError, CompilationErrorKind, CompilationResult}, + compilation_error::CompilationError, + compilation_error_kind::CompilationErrorKind, configuration::Configuration, expression::Expression, fragment::Fragment, - function::{evaluate_function, resolve_function}, + function::Function, function_context::FunctionContext, functions::Functions, interrupt_guard::InterruptGuard, @@ -45,7 +46,7 @@ pub(crate) use crate::{ recipe::Recipe, recipe_context::RecipeContext, recipe_resolver::RecipeResolver, - runtime_error::{RunResult, RuntimeError}, + runtime_error::RuntimeError, shebang::Shebang, state::State, string_literal::StringLiteral, @@ -56,6 +57,10 @@ pub(crate) use crate::{ verbosity::Verbosity, }; +pub type CompilationResult<'a, T> = Result>; + +pub type RunResult<'a, T> = Result>; + #[allow(unused_imports)] pub(crate) use std::io::prelude::*; diff --git a/src/compilation_error.rs b/src/compilation_error.rs index 576a484..f02c912 100644 --- a/src/compilation_error.rs +++ b/src/compilation_error.rs @@ -2,8 +2,6 @@ use crate::common::*; use crate::misc::{maybe_s, show_whitespace, write_error_context, Or}; -pub type CompilationResult<'a, T> = Result>; - #[derive(Debug, PartialEq)] pub struct CompilationError<'a> { pub text: &'a str, @@ -14,96 +12,6 @@ pub struct CompilationError<'a> { pub kind: CompilationErrorKind<'a>, } -#[derive(Debug, PartialEq)] -pub enum CompilationErrorKind<'a> { - AliasShadowsRecipe { - alias: &'a str, - recipe_line: usize, - }, - CircularRecipeDependency { - recipe: &'a str, - circle: Vec<&'a str>, - }, - CircularVariableDependency { - variable: &'a str, - circle: Vec<&'a str>, - }, - DependencyHasParameters { - recipe: &'a str, - dependency: &'a str, - }, - DuplicateAlias { - alias: &'a str, - first: usize, - }, - DuplicateDependency { - recipe: &'a str, - dependency: &'a str, - }, - DuplicateParameter { - recipe: &'a str, - parameter: &'a str, - }, - DuplicateRecipe { - recipe: &'a str, - first: usize, - }, - DuplicateVariable { - variable: &'a str, - }, - ExtraLeadingWhitespace, - FunctionArgumentCountMismatch { - function: &'a str, - found: usize, - expected: usize, - }, - InconsistentLeadingWhitespace { - expected: &'a str, - found: &'a str, - }, - Internal { - message: String, - }, - InvalidEscapeSequence { - character: char, - }, - MixedLeadingWhitespace { - whitespace: &'a str, - }, - ParameterFollowsVariadicParameter { - parameter: &'a str, - }, - ParameterShadowsVariable { - parameter: &'a str, - }, - RequiredParameterFollowsDefaultParameter { - parameter: &'a str, - }, - UndefinedVariable { - variable: &'a str, - }, - UnexpectedToken { - expected: Vec, - found: TokenKind, - }, - UnknownAliasTarget { - alias: &'a str, - target: &'a str, - }, - UnknownDependency { - recipe: &'a str, - unknown: &'a str, - }, - UnknownFunction { - function: &'a str, - }, - UnknownStartOfToken, - UnpairedCarriageReturn, - UnterminatedInterpolation, - UnterminatedString, - UnterminatedBacktick, -} - impl<'a> Display for CompilationError<'a> { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { use CompilationErrorKind::*; diff --git a/src/compilation_error_kind.rs b/src/compilation_error_kind.rs new file mode 100644 index 0000000..4da7f0e --- /dev/null +++ b/src/compilation_error_kind.rs @@ -0,0 +1,91 @@ +use crate::common::*; + +#[derive(Debug, PartialEq)] +pub enum CompilationErrorKind<'a> { + AliasShadowsRecipe { + alias: &'a str, + recipe_line: usize, + }, + CircularRecipeDependency { + recipe: &'a str, + circle: Vec<&'a str>, + }, + CircularVariableDependency { + variable: &'a str, + circle: Vec<&'a str>, + }, + DependencyHasParameters { + recipe: &'a str, + dependency: &'a str, + }, + DuplicateAlias { + alias: &'a str, + first: usize, + }, + DuplicateDependency { + recipe: &'a str, + dependency: &'a str, + }, + DuplicateParameter { + recipe: &'a str, + parameter: &'a str, + }, + DuplicateRecipe { + recipe: &'a str, + first: usize, + }, + DuplicateVariable { + variable: &'a str, + }, + ExtraLeadingWhitespace, + FunctionArgumentCountMismatch { + function: &'a str, + found: usize, + expected: usize, + }, + InconsistentLeadingWhitespace { + expected: &'a str, + found: &'a str, + }, + Internal { + message: String, + }, + InvalidEscapeSequence { + character: char, + }, + MixedLeadingWhitespace { + whitespace: &'a str, + }, + ParameterFollowsVariadicParameter { + parameter: &'a str, + }, + ParameterShadowsVariable { + parameter: &'a str, + }, + RequiredParameterFollowsDefaultParameter { + parameter: &'a str, + }, + UndefinedVariable { + variable: &'a str, + }, + UnexpectedToken { + expected: Vec, + found: TokenKind, + }, + UnknownAliasTarget { + alias: &'a str, + target: &'a str, + }, + UnknownDependency { + recipe: &'a str, + unknown: &'a str, + }, + UnknownFunction { + function: &'a str, + }, + UnknownStartOfToken, + UnpairedCarriageReturn, + UnterminatedInterpolation, + UnterminatedString, + UnterminatedBacktick, +} diff --git a/src/function.rs b/src/function.rs index bfcfe0b..2df48de 100644 --- a/src/function.rs +++ b/src/function.rs @@ -20,7 +20,7 @@ lazy_static! { .collect(); } -enum Function { +pub enum Function { Nullary(fn(&FunctionContext) -> Result), Unary(fn(&FunctionContext, &str) -> Result), Binary(fn(&FunctionContext, &str, &str) -> Result), @@ -35,64 +35,64 @@ impl Function { Binary(_) => 2, } } -} -pub fn resolve_function<'a>(token: &Token<'a>, argc: usize) -> CompilationResult<'a, ()> { - let name = token.lexeme(); - if let Some(function) = FUNCTIONS.get(&name) { - use self::Function::*; - match (function, argc) { - (&Nullary(_), 0) | (&Unary(_), 1) | (&Binary(_), 2) => Ok(()), - _ => Err( - token.error(CompilationErrorKind::FunctionArgumentCountMismatch { - function: name, - found: argc, - expected: function.argc(), - }), - ), + pub fn resolve<'a>(token: &Token<'a>, argc: usize) -> CompilationResult<'a, ()> { + let name = token.lexeme(); + if let Some(function) = FUNCTIONS.get(&name) { + use self::Function::*; + match (function, argc) { + (&Nullary(_), 0) | (&Unary(_), 1) | (&Binary(_), 2) => Ok(()), + _ => Err( + token.error(CompilationErrorKind::FunctionArgumentCountMismatch { + function: name, + found: argc, + expected: function.argc(), + }), + ), + } + } else { + Err(token.error(CompilationErrorKind::UnknownFunction { + function: token.lexeme(), + })) } - } else { - Err(token.error(CompilationErrorKind::UnknownFunction { - function: token.lexeme(), - })) } -} -pub fn evaluate_function<'a>( - token: &Token<'a>, - name: &'a str, - context: &FunctionContext, - arguments: &[String], -) -> RunResult<'a, String> { - if let Some(function) = FUNCTIONS.get(name) { - use self::Function::*; - let argc = arguments.len(); - match (function, argc) { - (&Nullary(f), 0) => f(context).map_err(|message| RuntimeError::FunctionCall { - token: token.clone(), - message, - }), - (&Unary(f), 1) => f(context, &arguments[0]).map_err(|message| RuntimeError::FunctionCall { - token: token.clone(), - message, - }), - (&Binary(f), 2) => { - f(context, &arguments[0], &arguments[1]).map_err(|message| RuntimeError::FunctionCall { + pub fn evaluate<'a>( + token: &Token<'a>, + name: &'a str, + context: &FunctionContext, + arguments: &[String], + ) -> RunResult<'a, String> { + if let Some(function) = FUNCTIONS.get(name) { + use self::Function::*; + let argc = arguments.len(); + match (function, argc) { + (&Nullary(f), 0) => f(context).map_err(|message| RuntimeError::FunctionCall { token: token.clone(), message, - }) + }), + (&Unary(f), 1) => f(context, &arguments[0]).map_err(|message| RuntimeError::FunctionCall { + token: token.clone(), + message, + }), + (&Binary(f), 2) => { + f(context, &arguments[0], &arguments[1]).map_err(|message| RuntimeError::FunctionCall { + token: token.clone(), + message, + }) + } + _ => Err(RuntimeError::Internal { + message: format!( + "attempted to evaluate function `{}` with {} arguments", + name, argc + ), + }), } - _ => Err(RuntimeError::Internal { - message: format!( - "attempted to evaluate function `{}` with {} arguments", - name, argc - ), - }), + } else { + Err(RuntimeError::Internal { + message: format!("attempted to evaluate unknown function: `{}`", name), + }) } - } else { - Err(RuntimeError::Internal { - message: format!("attempted to evaluate unknown function: `{}`", name), - }) } } diff --git a/src/lib.rs b/src/lib.rs index c93b53a..2c19f86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ mod color; mod command_ext; mod common; mod compilation_error; +mod compilation_error_kind; mod configuration; mod expression; mod fragment; diff --git a/src/recipe_resolver.rs b/src/recipe_resolver.rs index 7b9b6d1..c540cc8 100644 --- a/src/recipe_resolver.rs +++ b/src/recipe_resolver.rs @@ -71,7 +71,7 @@ impl<'a, 'b> RecipeResolver<'a, 'b> { } fn resolve_function(&self, function: &Token, argc: usize) -> CompilationResult<'a, ()> { - resolve_function(function, argc).map_err(|error| CompilationError { + Function::resolve(function, argc).map_err(|error| CompilationError { offset: error.offset, line: error.line, column: error.column, diff --git a/src/runtime_error.rs b/src/runtime_error.rs index f461c82..5c999ce 100644 --- a/src/runtime_error.rs +++ b/src/runtime_error.rs @@ -4,8 +4,6 @@ use brev::OutputError; use crate::misc::{maybe_s, ticks, write_error_context, And, Or, Tick}; -pub type RunResult<'a, T> = Result>; - fn write_token_error_context(f: &mut Formatter, token: &Token) -> Result<(), fmt::Error> { write_error_context( f,