Begin adding fancy errors
This commit is contained in:
parent
4805a53269
commit
77134e5292
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -11,6 +11,16 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "annotate-snippets"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.13"
|
version = "0.6.13"
|
||||||
@ -140,6 +150,7 @@ checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
|||||||
name = "dust-lang"
|
name = "dust-lang"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"annotate-snippets",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"rand",
|
"rand",
|
||||||
"rayon",
|
"rayon",
|
||||||
@ -394,6 +405,12 @@ version = "1.0.12"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -9,6 +9,7 @@ readme.workspace = true
|
|||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
annotate-snippets = "0.11.4"
|
||||||
env_logger = "0.11.3"
|
env_logger = "0.11.3"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
rayon = "1.9.0"
|
rayon = "1.9.0"
|
||||||
|
@ -85,11 +85,13 @@ impl<'a> Analyzer<'a> {
|
|||||||
(Some(Type::Integer), _) | (Some(Type::Float), _) | (Some(Type::String), _) => {
|
(Some(Type::Integer), _) | (Some(Type::Float), _) | (Some(Type::String), _) => {
|
||||||
return Err(AnalyzerError::ExpectedIntegerFloatOrString {
|
return Err(AnalyzerError::ExpectedIntegerFloatOrString {
|
||||||
actual: right.as_ref().clone(),
|
actual: right.as_ref().clone(),
|
||||||
|
position: right.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(AnalyzerError::ExpectedIntegerFloatOrString {
|
return Err(AnalyzerError::ExpectedIntegerFloatOrString {
|
||||||
actual: left.as_ref().clone(),
|
actual: left.as_ref().clone(),
|
||||||
|
position: left.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,6 +105,7 @@ impl<'a> Analyzer<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(AnalyzerError::ExpectedIdentifier {
|
return Err(AnalyzerError::ExpectedIdentifier {
|
||||||
actual: left.as_ref().clone(),
|
actual: left.as_ref().clone(),
|
||||||
|
position: left.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,12 +119,14 @@ impl<'a> Analyzer<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(AnalyzerError::ExpectedIdentifier {
|
return Err(AnalyzerError::ExpectedIdentifier {
|
||||||
actual: function.as_ref().clone(),
|
actual: function.as_ref().clone(),
|
||||||
|
position: function.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Statement::Identifier(_) => {
|
Statement::Identifier(_) => {
|
||||||
return Err(AnalyzerError::UnexpectedIdentifier {
|
return Err(AnalyzerError::UnexpectedIdentifier {
|
||||||
identifier: node.clone(),
|
identifier: node.clone(),
|
||||||
|
position: node.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Statement::List(statements) => {
|
Statement::List(statements) => {
|
||||||
@ -136,6 +141,7 @@ impl<'a> Analyzer<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(AnalyzerError::ExpectedIntegerOrFloat {
|
return Err(AnalyzerError::ExpectedIntegerOrFloat {
|
||||||
actual: left.as_ref().clone(),
|
actual: left.as_ref().clone(),
|
||||||
|
position: left.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +151,7 @@ impl<'a> Analyzer<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(AnalyzerError::ExpectedIntegerOrFloat {
|
return Err(AnalyzerError::ExpectedIntegerOrFloat {
|
||||||
actual: right.as_ref().clone(),
|
actual: right.as_ref().clone(),
|
||||||
|
position: right.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +166,7 @@ impl<'a> Analyzer<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(AnalyzerError::ExpectedIdentifierOrValue {
|
return Err(AnalyzerError::ExpectedIdentifierOrValue {
|
||||||
actual: left.as_ref().clone(),
|
actual: left.as_ref().clone(),
|
||||||
|
position: left.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,6 +176,7 @@ impl<'a> Analyzer<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(AnalyzerError::ExpectedIntegerOrFloat {
|
return Err(AnalyzerError::ExpectedIntegerOrFloat {
|
||||||
actual: left.as_ref().clone(),
|
actual: left.as_ref().clone(),
|
||||||
|
position: left.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,13 +192,13 @@ impl<'a> Analyzer<'a> {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum AnalyzerError {
|
pub enum AnalyzerError {
|
||||||
ExpectedBoolean { actual: Node },
|
ExpectedBoolean { actual: Node, position: Span },
|
||||||
ExpectedFunction { actual: Node },
|
ExpectedFunction { actual: Node, position: Span },
|
||||||
ExpectedIdentifier { actual: Node },
|
ExpectedIdentifier { actual: Node, position: Span },
|
||||||
ExpectedIdentifierOrValue { actual: Node },
|
ExpectedIdentifierOrValue { actual: Node, position: Span },
|
||||||
ExpectedIntegerOrFloat { actual: Node },
|
ExpectedIntegerOrFloat { actual: Node, position: Span },
|
||||||
ExpectedIntegerFloatOrString { actual: Node },
|
ExpectedIntegerFloatOrString { actual: Node, position: Span },
|
||||||
UnexpectedIdentifier { identifier: Node },
|
UnexpectedIdentifier { identifier: Node, position: Span },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for AnalyzerError {}
|
impl Error for AnalyzerError {}
|
||||||
@ -197,25 +206,25 @@ impl Error for AnalyzerError {}
|
|||||||
impl Display for AnalyzerError {
|
impl Display for AnalyzerError {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
AnalyzerError::ExpectedBoolean { actual } => {
|
AnalyzerError::ExpectedBoolean { actual, .. } => {
|
||||||
write!(f, "Expected boolean, found {}", actual)
|
write!(f, "Expected boolean, found {}", actual)
|
||||||
}
|
}
|
||||||
AnalyzerError::ExpectedFunction { actual } => {
|
AnalyzerError::ExpectedFunction { actual, .. } => {
|
||||||
write!(f, "Expected function, found {}", actual)
|
write!(f, "Expected function, found {}", actual)
|
||||||
}
|
}
|
||||||
AnalyzerError::ExpectedIdentifier { actual } => {
|
AnalyzerError::ExpectedIdentifier { actual, .. } => {
|
||||||
write!(f, "Expected identifier, found {}", actual)
|
write!(f, "Expected identifier, found {}", actual)
|
||||||
}
|
}
|
||||||
AnalyzerError::ExpectedIdentifierOrValue { actual } => {
|
AnalyzerError::ExpectedIdentifierOrValue { actual, .. } => {
|
||||||
write!(f, "Expected identifier or value, found {}", actual)
|
write!(f, "Expected identifier or value, found {}", actual)
|
||||||
}
|
}
|
||||||
AnalyzerError::ExpectedIntegerOrFloat { actual } => {
|
AnalyzerError::ExpectedIntegerOrFloat { actual, .. } => {
|
||||||
write!(f, "Expected integer or float, found {}", actual)
|
write!(f, "Expected integer or float, found {}", actual)
|
||||||
}
|
}
|
||||||
AnalyzerError::ExpectedIntegerFloatOrString { actual } => {
|
AnalyzerError::ExpectedIntegerFloatOrString { actual, .. } => {
|
||||||
write!(f, "Expected integer, float, or string, found {}", actual)
|
write!(f, "Expected integer, float, or string, found {}", actual)
|
||||||
}
|
}
|
||||||
AnalyzerError::UnexpectedIdentifier { identifier } => {
|
AnalyzerError::UnexpectedIdentifier { identifier, .. } => {
|
||||||
write!(f, "Unexpected identifier {}", identifier)
|
write!(f, "Unexpected identifier {}", identifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,7 +255,8 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
analyzer.analyze(),
|
analyzer.analyze(),
|
||||||
Err(AnalyzerError::ExpectedIntegerFloatOrString {
|
Err(AnalyzerError::ExpectedIntegerFloatOrString {
|
||||||
actual: Node::new(Statement::Constant(Value::float(1.0)), (1, 2))
|
actual: Node::new(Statement::Constant(Value::float(1.0)), (1, 2)),
|
||||||
|
position: (1, 2)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -269,7 +279,8 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
analyzer.analyze(),
|
analyzer.analyze(),
|
||||||
Err(AnalyzerError::ExpectedIntegerFloatOrString {
|
Err(AnalyzerError::ExpectedIntegerFloatOrString {
|
||||||
actual: Node::new(Statement::Constant(Value::boolean(true)), (0, 1))
|
actual: Node::new(Statement::Constant(Value::boolean(true)), (0, 1)),
|
||||||
|
position: (0, 1)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -299,7 +310,8 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
analyzer.analyze(),
|
analyzer.analyze(),
|
||||||
Err(AnalyzerError::ExpectedIntegerOrFloat {
|
Err(AnalyzerError::ExpectedIntegerOrFloat {
|
||||||
actual: Node::new(Statement::Constant(Value::boolean(true)), (0, 1))
|
actual: Node::new(Statement::Constant(Value::boolean(true)), (0, 1)),
|
||||||
|
position: (0, 1)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -328,7 +340,8 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
analyzer.analyze(),
|
analyzer.analyze(),
|
||||||
Err(AnalyzerError::ExpectedIntegerOrFloat {
|
Err(AnalyzerError::ExpectedIntegerOrFloat {
|
||||||
actual: Node::new(Statement::Constant(Value::boolean(true)), (0, 1))
|
actual: Node::new(Statement::Constant(Value::boolean(true)), (0, 1)),
|
||||||
|
position: (0, 1)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -354,7 +367,8 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
analyzer.analyze(),
|
analyzer.analyze(),
|
||||||
Err(AnalyzerError::ExpectedIntegerOrFloat {
|
Err(AnalyzerError::ExpectedIntegerOrFloat {
|
||||||
actual: Node::new(Statement::Constant(Value::boolean(false)), (1, 2))
|
actual: Node::new(Statement::Constant(Value::boolean(false)), (1, 2)),
|
||||||
|
position: (1, 2)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -377,7 +391,8 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
analyzer.analyze(),
|
analyzer.analyze(),
|
||||||
Err(AnalyzerError::ExpectedIdentifier {
|
Err(AnalyzerError::ExpectedIdentifier {
|
||||||
actual: Node::new(Statement::Constant(Value::integer(1)), (0, 1))
|
actual: Node::new(Statement::Constant(Value::integer(1)), (0, 1)),
|
||||||
|
position: (0, 1)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -397,7 +412,8 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
analyzer.analyze(),
|
analyzer.analyze(),
|
||||||
Err(AnalyzerError::UnexpectedIdentifier {
|
Err(AnalyzerError::UnexpectedIdentifier {
|
||||||
identifier: Node::new(Statement::Identifier(Identifier::new("x")), (0, 1))
|
identifier: Node::new(Statement::Identifier(Identifier::new("x")), (0, 1)),
|
||||||
|
position: (0, 1)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
use annotate_snippets::{Level, Renderer, Snippet};
|
||||||
use std::{error::Error, fmt::Display};
|
use std::{error::Error, fmt::Display};
|
||||||
|
|
||||||
use crate::VmError;
|
use crate::{AnalyzerError, VmError};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct DustError<'src> {
|
pub struct DustError<'src> {
|
||||||
@ -8,6 +9,51 @@ pub struct DustError<'src> {
|
|||||||
source: &'src str,
|
source: &'src str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> DustError<'src> {
|
||||||
|
pub fn new(vm_error: VmError, source: &'src str) -> Self {
|
||||||
|
Self { vm_error, source }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn report(&self) -> String {
|
||||||
|
let title = match &self.vm_error {
|
||||||
|
VmError::AnaylyzerError(_) => "Analyzer error",
|
||||||
|
VmError::ParseError(_) => "Parse error",
|
||||||
|
VmError::ValueError(_) => "Value error",
|
||||||
|
VmError::BuiltInFunctionCallError(_) => "Runtime error",
|
||||||
|
_ => "Analysis Failure",
|
||||||
|
};
|
||||||
|
let span = match &self.vm_error {
|
||||||
|
VmError::AnaylyzerError(analyzer_error) => match analyzer_error {
|
||||||
|
AnalyzerError::ExpectedBoolean { position, .. } => position,
|
||||||
|
AnalyzerError::ExpectedFunction { position, .. } => position,
|
||||||
|
AnalyzerError::ExpectedIdentifier { position, .. } => position,
|
||||||
|
AnalyzerError::ExpectedIdentifierOrValue { position, .. } => position,
|
||||||
|
AnalyzerError::ExpectedIntegerOrFloat { position, .. } => position,
|
||||||
|
AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => position,
|
||||||
|
AnalyzerError::UnexpectedIdentifier { position, .. } => position,
|
||||||
|
},
|
||||||
|
VmError::ParseError(_) => todo!(),
|
||||||
|
VmError::ValueError(_) => todo!(),
|
||||||
|
VmError::BuiltInFunctionCallError(_) => todo!(),
|
||||||
|
VmError::ExpectedIdentifier { position } => position,
|
||||||
|
VmError::ExpectedIdentifierOrInteger { position } => position,
|
||||||
|
VmError::ExpectedInteger { position } => position,
|
||||||
|
VmError::ExpectedFunction { position, .. } => position,
|
||||||
|
VmError::ExpectedList { position } => position,
|
||||||
|
VmError::ExpectedValue { position } => position,
|
||||||
|
};
|
||||||
|
let label = self.vm_error.to_string();
|
||||||
|
|
||||||
|
let message = Level::Error.title(title).snippet(
|
||||||
|
Snippet::source(self.source).annotation(Level::Info.span(span.0..span.1).label(&label)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let renderer = Renderer::styled();
|
||||||
|
|
||||||
|
format!("{}", renderer.render(message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Error for DustError<'_> {
|
impl Error for DustError<'_> {
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
Some(&self.vm_error)
|
Some(&self.vm_error)
|
||||||
|
@ -20,6 +20,7 @@ pub mod vm;
|
|||||||
pub use abstract_tree::{AbstractSyntaxTree, Node, Statement};
|
pub use abstract_tree::{AbstractSyntaxTree, Node, Statement};
|
||||||
pub use analyzer::{analyze, Analyzer, AnalyzerError};
|
pub use analyzer::{analyze, Analyzer, AnalyzerError};
|
||||||
pub use built_in_function::{BuiltInFunction, BuiltInFunctionError};
|
pub use built_in_function::{BuiltInFunction, BuiltInFunctionError};
|
||||||
|
pub use dust_error::DustError;
|
||||||
pub use identifier::Identifier;
|
pub use identifier::Identifier;
|
||||||
pub use lex::{lex, LexError, Lexer};
|
pub use lex::{lex, LexError, Lexer};
|
||||||
pub use parse::{parse, ParseError, Parser};
|
pub use parse::{parse, ParseError, Parser};
|
||||||
|
@ -235,7 +235,7 @@ impl<'src> Parser<'src> {
|
|||||||
} else {
|
} else {
|
||||||
Err(ParseError::ExpectedClosingParenthesis {
|
Err(ParseError::ExpectedClosingParenthesis {
|
||||||
actual: self.current.0.to_owned(),
|
actual: self.current.0.to_owned(),
|
||||||
span: self.current.1,
|
position: self.current.1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,7 +265,7 @@ impl<'src> Parser<'src> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(ParseError::ExpectedClosingSquareBrace {
|
return Err(ParseError::ExpectedClosingSquareBrace {
|
||||||
actual: self.current.0.to_owned(),
|
actual: self.current.0.to_owned(),
|
||||||
span: self.current.1,
|
position: self.current.1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ impl<'src> Parser<'src> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(ParseError::ExpectedOpeningParenthesis {
|
return Err(ParseError::ExpectedOpeningParenthesis {
|
||||||
actual: self.current.0.to_owned(),
|
actual: self.current.0.to_owned(),
|
||||||
span: self.current.1,
|
position: self.current.1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ impl<'src> Parser<'src> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(ParseError::ExpectedClosingParenthesis {
|
return Err(ParseError::ExpectedClosingParenthesis {
|
||||||
actual: self.current.0.to_owned(),
|
actual: self.current.0.to_owned(),
|
||||||
span: self.current.1,
|
position: self.current.1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,9 +349,9 @@ impl<'src> Parser<'src> {
|
|||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
LexError(LexError),
|
LexError(LexError),
|
||||||
|
|
||||||
ExpectedClosingParenthesis { actual: TokenOwned, span: Span },
|
ExpectedClosingParenthesis { actual: TokenOwned, position: Span },
|
||||||
ExpectedClosingSquareBrace { actual: TokenOwned, span: Span },
|
ExpectedClosingSquareBrace { actual: TokenOwned, position: Span },
|
||||||
ExpectedOpeningParenthesis { actual: TokenOwned, span: Span },
|
ExpectedOpeningParenthesis { actual: TokenOwned, position: Span },
|
||||||
UnexpectedToken(TokenOwned),
|
UnexpectedToken(TokenOwned),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,22 +368,16 @@ impl Display for ParseError {
|
|||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::LexError(error) => write!(f, "{}", error),
|
Self::LexError(error) => write!(f, "{}", error),
|
||||||
Self::ExpectedClosingParenthesis { actual, span } => write!(
|
Self::ExpectedClosingParenthesis { actual, .. } => {
|
||||||
f,
|
write!(f, "Expected closing parenthesis, found {actual}",)
|
||||||
"Expected closing parenthesis, found {} at {:?}",
|
}
|
||||||
actual, span
|
Self::ExpectedClosingSquareBrace { actual, .. } => {
|
||||||
),
|
write!(f, "Expected closing square brace, found {actual}",)
|
||||||
Self::ExpectedClosingSquareBrace { actual, span } => write!(
|
}
|
||||||
f,
|
Self::ExpectedOpeningParenthesis { actual, .. } => {
|
||||||
"Expected closing square brace, found {:?} at {:?}",
|
write!(f, "Expected opening parenthesis, found {actual}",)
|
||||||
actual, span
|
}
|
||||||
),
|
Self::UnexpectedToken(actual) => write!(f, "Unexpected token {actual}"),
|
||||||
Self::ExpectedOpeningParenthesis { actual, span } => write!(
|
|
||||||
f,
|
|
||||||
"Expected opening parenthesis, found {:?} at {:?}",
|
|
||||||
actual, span
|
|
||||||
),
|
|
||||||
Self::UnexpectedToken(actual) => write!(f, "Unexpected token {:?}", actual),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,7 @@ pub enum VmError {
|
|||||||
|
|
||||||
// Anaylsis Failures
|
// Anaylsis Failures
|
||||||
// These should be prevented by running the analyzer before the VM
|
// These should be prevented by running the analyzer before the VM
|
||||||
BuiltInFunctionCallFailed(BuiltInFunctionError),
|
BuiltInFunctionCallError(BuiltInFunctionError),
|
||||||
ExpectedIdentifier { position: Span },
|
ExpectedIdentifier { position: Span },
|
||||||
ExpectedIdentifierOrInteger { position: Span },
|
ExpectedIdentifierOrInteger { position: Span },
|
||||||
ExpectedInteger { position: Span },
|
ExpectedInteger { position: Span },
|
||||||
@ -261,7 +261,7 @@ pub enum VmError {
|
|||||||
|
|
||||||
impl From<BuiltInFunctionError> for VmError {
|
impl From<BuiltInFunctionError> for VmError {
|
||||||
fn from(v: BuiltInFunctionError) -> Self {
|
fn from(v: BuiltInFunctionError) -> Self {
|
||||||
Self::BuiltInFunctionCallFailed(v)
|
Self::BuiltInFunctionCallError(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +289,7 @@ impl Error for VmError {
|
|||||||
Self::AnaylyzerError(analyzer_error) => Some(analyzer_error),
|
Self::AnaylyzerError(analyzer_error) => Some(analyzer_error),
|
||||||
Self::ParseError(parse_error) => Some(parse_error),
|
Self::ParseError(parse_error) => Some(parse_error),
|
||||||
Self::ValueError(value_error) => Some(value_error),
|
Self::ValueError(value_error) => Some(value_error),
|
||||||
Self::BuiltInFunctionCallFailed(built_in_function_error) => {
|
Self::BuiltInFunctionCallError(built_in_function_error) => {
|
||||||
Some(built_in_function_error)
|
Some(built_in_function_error)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -303,7 +303,7 @@ impl Display for VmError {
|
|||||||
Self::AnaylyzerError(analyzer_error) => write!(f, "{}", analyzer_error),
|
Self::AnaylyzerError(analyzer_error) => write!(f, "{}", analyzer_error),
|
||||||
Self::ParseError(parse_error) => write!(f, "{}", parse_error),
|
Self::ParseError(parse_error) => write!(f, "{}", parse_error),
|
||||||
Self::ValueError(value_error) => write!(f, "{}", value_error),
|
Self::ValueError(value_error) => write!(f, "{}", value_error),
|
||||||
Self::BuiltInFunctionCallFailed(built_in_function_error) => {
|
Self::BuiltInFunctionCallError(built_in_function_error) => {
|
||||||
write!(f, "{}", built_in_function_error)
|
write!(f, "{}", built_in_function_error)
|
||||||
}
|
}
|
||||||
Self::ExpectedFunction { actual, position } => {
|
Self::ExpectedFunction { actual, position } => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{collections::HashMap, fs::read_to_string};
|
use std::{collections::HashMap, fs::read_to_string};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use dust_lang::run;
|
use dust_lang::{run, DustError, Identifier, Value};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
@ -15,22 +15,24 @@ fn main() {
|
|||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
let mut variables = HashMap::new();
|
let mut variables = HashMap::new();
|
||||||
|
|
||||||
let result = if let Some(command) = &args.command {
|
if let Some(command) = &args.command {
|
||||||
run(command, &mut variables)
|
run_and_display_errors(command, &mut variables);
|
||||||
} else if let Some(path) = &args.path {
|
} else if let Some(path) = &args.path {
|
||||||
let content = read_to_string(path).unwrap();
|
let source = read_to_string(path).expect("Failed to read file");
|
||||||
|
|
||||||
run(&content, &mut variables)
|
run_and_display_errors(&source, &mut variables)
|
||||||
} else {
|
} else {
|
||||||
panic!("No command or path provided");
|
panic!("No command or path provided");
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
match result {
|
fn run_and_display_errors(source: &str, variables: &mut HashMap<Identifier, Value>) {
|
||||||
|
match run(source, variables) {
|
||||||
Ok(return_value) => {
|
Ok(return_value) => {
|
||||||
if let Some(value) = return_value {
|
if let Some(value) = return_value {
|
||||||
println!("{}", value);
|
println!("{}", value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(error) => eprintln!("{}", error),
|
Err(error) => eprintln!("{}", DustError::new(error, source).report()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
rust-toolchain
Normal file
1
rust-toolchain
Normal file
@ -0,0 +1 @@
|
|||||||
|
nightly
|
Loading…
Reference in New Issue
Block a user