This commit is contained in:
Jeff 2024-08-20 04:38:15 -04:00
parent c0ab5a84a2
commit 8b5eb9977c
5 changed files with 88 additions and 30 deletions

View File

@ -37,7 +37,7 @@ pub fn analyze(source: &str) -> Result<(), DustError> {
analyzer analyzer
.analyze() .analyze()
.map_err(|analysis_error| DustError::AnalysisError { .map_err(|analysis_error| DustError::Analysis {
analysis_error, analysis_error,
source, source,
}) })
@ -535,7 +535,7 @@ mod tests {
assert_eq!( assert_eq!(
analyze(source), analyze(source),
Err(DustError::AnalysisError { Err(DustError::Analysis {
analysis_error: AnalysisError::TypeConflict { analysis_error: AnalysisError::TypeConflict {
actual_expression: Expression::literal(1.0, (45, 48)), actual_expression: Expression::literal(1.0, (45, 48)),
actual_type: Type::Float, actual_type: Type::Float,
@ -555,7 +555,7 @@ mod tests {
assert_eq!( assert_eq!(
analyze(source), analyze(source),
Err(DustError::AnalysisError { Err(DustError::Analysis {
analysis_error: AnalysisError::TypeConflict { analysis_error: AnalysisError::TypeConflict {
actual_expression: Expression::literal(1.0, (45, 48)), actual_expression: Expression::literal(1.0, (45, 48)),
actual_type: Type::Float, actual_type: Type::Float,

View File

@ -240,8 +240,8 @@ impl Expression {
)) ))
} }
pub fn r#if(r#if: IfExpression, position: Span) -> Self { pub fn r#if(if_expression: IfExpression, position: Span) -> Self {
Self::If(Node::new(Box::new(r#if), position)) Self::If(Node::new(Box::new(if_expression), position))
} }
pub fn literal<T: Into<LiteralExpression>>(into_literal: T, position: Span) -> Self { pub fn literal<T: Into<LiteralExpression>>(into_literal: T, position: Span) -> Self {
@ -888,6 +888,39 @@ pub enum IfExpression {
}, },
} }
impl IfExpression {
pub fn r#if(condition: Expression, if_block: Node<BlockExpression>) -> Self {
IfExpression::If {
condition,
if_block,
}
}
pub fn if_else(
condition: Expression,
if_block: Node<BlockExpression>,
else_block: Node<BlockExpression>,
) -> Self {
IfExpression::IfElse {
condition,
if_block,
r#else: ElseExpression::Block(else_block),
}
}
pub fn if_else_if(
condition: Expression,
if_block: Node<BlockExpression>,
else_if: Node<Box<IfExpression>>,
) -> Self {
IfExpression::IfElse {
condition,
if_block,
r#else: ElseExpression::If(else_if),
}
}
}
impl Display for IfExpression { impl Display for IfExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
@ -1010,8 +1043,8 @@ impl Display for LoopExpression {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum StructExpression { pub enum StructExpression {
// The unit struct is omitted because it is redundant with a plain identifier // The unit struct expression is omitted because it is redundant with identifier expressions
// The tuple struct is omitted because it is redundant with the call expression // The tuple struct expression is omitted because it is redundant with call expression
Fields { Fields {
name: Node<Identifier>, name: Node<Identifier>,
fields: Vec<(Node<Identifier>, Expression)>, fields: Vec<(Node<Identifier>, Expression)>,

View File

@ -8,49 +8,74 @@ use crate::{AnalysisError, LexError, ParseError, RuntimeError};
/// corresponding source code. /// corresponding source code.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum DustError<'src> { pub enum DustError<'src> {
VmError { Runtime {
runtime_error: RuntimeError, runtime_error: RuntimeError,
source: &'src str, source: &'src str,
}, },
AnalysisError { Analysis {
analysis_error: AnalysisError, analysis_error: AnalysisError,
source: &'src str, source: &'src str,
}, },
ParseError { Parse {
parse_error: ParseError, parse_error: ParseError,
source: &'src str, source: &'src str,
}, },
LexError { Lex {
lex_error: LexError, lex_error: LexError,
source: &'src str, source: &'src str,
}, },
} }
impl<'src> DustError<'src> { impl<'src> DustError<'src> {
pub fn runtime(runtime_error: RuntimeError, source: &'src str) -> Self {
DustError::Runtime {
runtime_error,
source,
}
}
pub fn analysis(analysis_error: AnalysisError, source: &'src str) -> Self {
DustError::Analysis {
analysis_error,
source,
}
}
pub fn parse(parse_error: ParseError, source: &'src str) -> Self {
DustError::Parse {
parse_error,
source,
}
}
pub fn lex(lex_error: LexError, source: &'src str) -> Self {
DustError::Lex { lex_error, source }
}
pub fn title(&self) -> &'static str { pub fn title(&self) -> &'static str {
match self { match self {
DustError::VmError { .. } => "Runtime error", DustError::Runtime { .. } => "Runtime error",
DustError::AnalysisError { .. } => "Analysis error", DustError::Analysis { .. } => "Analysis error",
DustError::ParseError { .. } => "Parse error", DustError::Parse { .. } => "Parse error",
DustError::LexError { .. } => "Lex error", DustError::Lex { .. } => "Lex error",
} }
} }
pub fn position(&self) -> (usize, usize) { pub fn position(&self) -> (usize, usize) {
match self { match self {
DustError::VmError { runtime_error, .. } => runtime_error.position(), DustError::Runtime { runtime_error, .. } => runtime_error.position(),
DustError::AnalysisError { analysis_error, .. } => analysis_error.position(), DustError::Analysis { analysis_error, .. } => analysis_error.position(),
DustError::ParseError { parse_error, .. } => parse_error.position(), DustError::Parse { parse_error, .. } => parse_error.position(),
DustError::LexError { lex_error, .. } => lex_error.position(), DustError::Lex { lex_error, .. } => lex_error.position(),
} }
} }
pub fn source(&self) -> &'src str { pub fn source(&self) -> &'src str {
match self { match self {
DustError::VmError { source, .. } => source, DustError::Runtime { source, .. } => source,
DustError::AnalysisError { source, .. } => source, DustError::Analysis { source, .. } => source,
DustError::ParseError { source, .. } => source, DustError::Parse { source, .. } => source,
DustError::LexError { source, .. } => source, DustError::Lex { source, .. } => source,
} }
} }
@ -71,10 +96,10 @@ impl<'src> DustError<'src> {
impl Display for DustError<'_> { impl Display for DustError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
DustError::VmError { runtime_error, .. } => write!(f, "{runtime_error}"), DustError::Runtime { runtime_error, .. } => write!(f, "{runtime_error}"),
DustError::AnalysisError { analysis_error, .. } => write!(f, "{analysis_error}"), DustError::Analysis { analysis_error, .. } => write!(f, "{analysis_error}"),
DustError::ParseError { parse_error, .. } => write!(f, "{parse_error}"), DustError::Parse { parse_error, .. } => write!(f, "{parse_error}"),
DustError::LexError { lex_error, .. } => write!(f, "{lex_error}"), DustError::Lex { lex_error, .. } => write!(f, "{lex_error}"),
} }
} }
} }

View File

@ -61,7 +61,7 @@ pub fn parse_into<'src>(
loop { loop {
let node = parser let node = parser
.parse_statement() .parse_statement()
.map_err(|parse_error| DustError::ParseError { .map_err(|parse_error| DustError::Parse {
parse_error, parse_error,
source, source,
})?; })?;

View File

@ -61,14 +61,14 @@ pub fn run_with_context(source: &str, context: Context) -> Result<Option<Value>,
analyzer analyzer
.analyze() .analyze()
.map_err(|analysis_error| DustError::AnalysisError { .map_err(|analysis_error| DustError::Analysis {
analysis_error, analysis_error,
source, source,
})?; })?;
let mut vm = Vm::new(abstract_syntax_tree, context); let mut vm = Vm::new(abstract_syntax_tree, context);
vm.run().map_err(|runtime_error| DustError::VmError { vm.run().map_err(|runtime_error| DustError::Runtime {
runtime_error, runtime_error,
source, source,
}) })