Move CompilationErrorKind into separate module (#416)
This commit is contained in:
parent
415c84ea39
commit
9c82a1e329
@ -116,7 +116,7 @@ impl<'a, 'b> AssignmentEvaluator<'a, 'b> {
|
|||||||
invocation_directory: &self.invocation_directory,
|
invocation_directory: &self.invocation_directory,
|
||||||
dotenv: self.dotenv,
|
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::String { ref cooked_string } => Ok(cooked_string.cooked.to_string()),
|
||||||
Expression::Backtick { raw, ref token } => {
|
Expression::Backtick { raw, ref token } => {
|
||||||
|
@ -77,7 +77,7 @@ impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> {
|
|||||||
ref token,
|
ref token,
|
||||||
ref arguments,
|
ref arguments,
|
||||||
..
|
..
|
||||||
} => resolve_function(token, arguments.len())?,
|
} => Function::resolve(token, arguments.len())?,
|
||||||
Expression::Concatination { ref lhs, ref rhs } => {
|
Expression::Concatination { ref lhs, ref rhs } => {
|
||||||
self.resolve_expression(lhs)?;
|
self.resolve_expression(lhs)?;
|
||||||
self.resolve_expression(rhs)?;
|
self.resolve_expression(rhs)?;
|
||||||
|
@ -26,11 +26,12 @@ pub(crate) use crate::{
|
|||||||
assignment_evaluator::AssignmentEvaluator,
|
assignment_evaluator::AssignmentEvaluator,
|
||||||
assignment_resolver::AssignmentResolver,
|
assignment_resolver::AssignmentResolver,
|
||||||
color::Color,
|
color::Color,
|
||||||
compilation_error::{CompilationError, CompilationErrorKind, CompilationResult},
|
compilation_error::CompilationError,
|
||||||
|
compilation_error_kind::CompilationErrorKind,
|
||||||
configuration::Configuration,
|
configuration::Configuration,
|
||||||
expression::Expression,
|
expression::Expression,
|
||||||
fragment::Fragment,
|
fragment::Fragment,
|
||||||
function::{evaluate_function, resolve_function},
|
function::Function,
|
||||||
function_context::FunctionContext,
|
function_context::FunctionContext,
|
||||||
functions::Functions,
|
functions::Functions,
|
||||||
interrupt_guard::InterruptGuard,
|
interrupt_guard::InterruptGuard,
|
||||||
@ -45,7 +46,7 @@ pub(crate) use crate::{
|
|||||||
recipe::Recipe,
|
recipe::Recipe,
|
||||||
recipe_context::RecipeContext,
|
recipe_context::RecipeContext,
|
||||||
recipe_resolver::RecipeResolver,
|
recipe_resolver::RecipeResolver,
|
||||||
runtime_error::{RunResult, RuntimeError},
|
runtime_error::RuntimeError,
|
||||||
shebang::Shebang,
|
shebang::Shebang,
|
||||||
state::State,
|
state::State,
|
||||||
string_literal::StringLiteral,
|
string_literal::StringLiteral,
|
||||||
@ -56,6 +57,10 @@ pub(crate) use crate::{
|
|||||||
verbosity::Verbosity,
|
verbosity::Verbosity,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub type CompilationResult<'a, T> = Result<T, CompilationError<'a>>;
|
||||||
|
|
||||||
|
pub type RunResult<'a, T> = Result<T, RuntimeError<'a>>;
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
pub(crate) use std::io::prelude::*;
|
pub(crate) use std::io::prelude::*;
|
||||||
|
|
||||||
|
@ -2,8 +2,6 @@ use crate::common::*;
|
|||||||
|
|
||||||
use crate::misc::{maybe_s, show_whitespace, write_error_context, Or};
|
use crate::misc::{maybe_s, show_whitespace, write_error_context, Or};
|
||||||
|
|
||||||
pub type CompilationResult<'a, T> = Result<T, CompilationError<'a>>;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct CompilationError<'a> {
|
pub struct CompilationError<'a> {
|
||||||
pub text: &'a str,
|
pub text: &'a str,
|
||||||
@ -14,96 +12,6 @@ pub struct CompilationError<'a> {
|
|||||||
pub kind: CompilationErrorKind<'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<TokenKind>,
|
|
||||||
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> {
|
impl<'a> Display for CompilationError<'a> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
use CompilationErrorKind::*;
|
use CompilationErrorKind::*;
|
||||||
|
91
src/compilation_error_kind.rs
Normal file
91
src/compilation_error_kind.rs
Normal file
@ -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<TokenKind>,
|
||||||
|
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,
|
||||||
|
}
|
102
src/function.rs
102
src/function.rs
@ -20,7 +20,7 @@ lazy_static! {
|
|||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Function {
|
pub enum Function {
|
||||||
Nullary(fn(&FunctionContext) -> Result<String, String>),
|
Nullary(fn(&FunctionContext) -> Result<String, String>),
|
||||||
Unary(fn(&FunctionContext, &str) -> Result<String, String>),
|
Unary(fn(&FunctionContext, &str) -> Result<String, String>),
|
||||||
Binary(fn(&FunctionContext, &str, &str) -> Result<String, String>),
|
Binary(fn(&FunctionContext, &str, &str) -> Result<String, String>),
|
||||||
@ -35,64 +35,64 @@ impl Function {
|
|||||||
Binary(_) => 2,
|
Binary(_) => 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_function<'a>(token: &Token<'a>, argc: usize) -> CompilationResult<'a, ()> {
|
pub fn resolve<'a>(token: &Token<'a>, argc: usize) -> CompilationResult<'a, ()> {
|
||||||
let name = token.lexeme();
|
let name = token.lexeme();
|
||||||
if let Some(function) = FUNCTIONS.get(&name) {
|
if let Some(function) = FUNCTIONS.get(&name) {
|
||||||
use self::Function::*;
|
use self::Function::*;
|
||||||
match (function, argc) {
|
match (function, argc) {
|
||||||
(&Nullary(_), 0) | (&Unary(_), 1) | (&Binary(_), 2) => Ok(()),
|
(&Nullary(_), 0) | (&Unary(_), 1) | (&Binary(_), 2) => Ok(()),
|
||||||
_ => Err(
|
_ => Err(
|
||||||
token.error(CompilationErrorKind::FunctionArgumentCountMismatch {
|
token.error(CompilationErrorKind::FunctionArgumentCountMismatch {
|
||||||
function: name,
|
function: name,
|
||||||
found: argc,
|
found: argc,
|
||||||
expected: function.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>(
|
pub fn evaluate<'a>(
|
||||||
token: &Token<'a>,
|
token: &Token<'a>,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
context: &FunctionContext,
|
context: &FunctionContext,
|
||||||
arguments: &[String],
|
arguments: &[String],
|
||||||
) -> RunResult<'a, String> {
|
) -> RunResult<'a, String> {
|
||||||
if let Some(function) = FUNCTIONS.get(name) {
|
if let Some(function) = FUNCTIONS.get(name) {
|
||||||
use self::Function::*;
|
use self::Function::*;
|
||||||
let argc = arguments.len();
|
let argc = arguments.len();
|
||||||
match (function, argc) {
|
match (function, argc) {
|
||||||
(&Nullary(f), 0) => f(context).map_err(|message| RuntimeError::FunctionCall {
|
(&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(),
|
token: token.clone(),
|
||||||
message,
|
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 {
|
} else {
|
||||||
message: format!(
|
Err(RuntimeError::Internal {
|
||||||
"attempted to evaluate function `{}` with {} arguments",
|
message: format!("attempted to evaluate unknown function: `{}`", name),
|
||||||
name, argc
|
})
|
||||||
),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Err(RuntimeError::Internal {
|
|
||||||
message: format!("attempted to evaluate unknown function: `{}`", name),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ mod color;
|
|||||||
mod command_ext;
|
mod command_ext;
|
||||||
mod common;
|
mod common;
|
||||||
mod compilation_error;
|
mod compilation_error;
|
||||||
|
mod compilation_error_kind;
|
||||||
mod configuration;
|
mod configuration;
|
||||||
mod expression;
|
mod expression;
|
||||||
mod fragment;
|
mod fragment;
|
||||||
|
@ -71,7 +71,7 @@ impl<'a, 'b> RecipeResolver<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_function(&self, function: &Token, argc: usize) -> CompilationResult<'a, ()> {
|
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,
|
offset: error.offset,
|
||||||
line: error.line,
|
line: error.line,
|
||||||
column: error.column,
|
column: error.column,
|
||||||
|
@ -4,8 +4,6 @@ use brev::OutputError;
|
|||||||
|
|
||||||
use crate::misc::{maybe_s, ticks, write_error_context, And, Or, Tick};
|
use crate::misc::{maybe_s, ticks, write_error_context, And, Or, Tick};
|
||||||
|
|
||||||
pub type RunResult<'a, T> = Result<T, RuntimeError<'a>>;
|
|
||||||
|
|
||||||
fn write_token_error_context(f: &mut Formatter, token: &Token) -> Result<(), fmt::Error> {
|
fn write_token_error_context(f: &mut Formatter, token: &Token) -> Result<(), fmt::Error> {
|
||||||
write_error_context(
|
write_error_context(
|
||||||
f,
|
f,
|
||||||
|
Loading…
Reference in New Issue
Block a user