Add native function errors
This commit is contained in:
parent
382d43ef77
commit
bd23853657
@ -18,7 +18,7 @@ pub use formatter::{format, Formatter};
|
||||
pub use identifier::Identifier;
|
||||
pub use instruction::Instruction;
|
||||
pub use lexer::{lex, LexError, Lexer};
|
||||
pub use native_function::NativeFunction;
|
||||
pub use native_function::{NativeFunction, NativeFunctionError};
|
||||
pub use operation::Operation;
|
||||
pub use parser::{parse, ParseError, Parser};
|
||||
pub use r#type::{EnumType, FunctionType, RangeableType, StructType, Type, TypeConflict};
|
||||
|
@ -1,11 +1,12 @@
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
io::{self, stdin, stdout, Write},
|
||||
string::{self},
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Instruction, Primitive, Span, Value, Vm, VmError};
|
||||
use crate::{AnnotatedError, Instruction, Primitive, Span, Value, Vm, VmError};
|
||||
|
||||
const PANIC: u8 = 0b0000_0000;
|
||||
|
||||
@ -252,7 +253,10 @@ impl NativeFunction {
|
||||
Some(message)
|
||||
};
|
||||
|
||||
return Err(VmError::Panic { message, position });
|
||||
return Err(VmError::NativeFunction(NativeFunctionError::Panic {
|
||||
message,
|
||||
position,
|
||||
}));
|
||||
}
|
||||
|
||||
// Type conversion
|
||||
@ -321,12 +325,12 @@ impl NativeFunction {
|
||||
NativeFunction::ReadLine => {
|
||||
let mut buffer = String::new();
|
||||
|
||||
stdin()
|
||||
.read_line(&mut buffer)
|
||||
.map_err(|io_error| VmError::Io {
|
||||
stdin().read_line(&mut buffer).map_err(|io_error| {
|
||||
VmError::NativeFunction(NativeFunctionError::Io {
|
||||
error: io_error.kind(),
|
||||
position,
|
||||
})?;
|
||||
})
|
||||
})?;
|
||||
|
||||
buffer = buffer.trim_end_matches('\n').to_string();
|
||||
|
||||
@ -335,9 +339,11 @@ impl NativeFunction {
|
||||
NativeFunction::Write => {
|
||||
let to_register = instruction.a();
|
||||
let mut stdout = stdout();
|
||||
let map_err = |io_error: io::Error| VmError::Io {
|
||||
error: io_error.kind(),
|
||||
position,
|
||||
let map_err = |io_error: io::Error| {
|
||||
VmError::NativeFunction(NativeFunctionError::Io {
|
||||
error: io_error.kind(),
|
||||
position,
|
||||
})
|
||||
};
|
||||
|
||||
let first_argument = to_register.saturating_sub(argument_count);
|
||||
@ -359,9 +365,11 @@ impl NativeFunction {
|
||||
}
|
||||
NativeFunction::WriteLine => {
|
||||
let mut stdout = stdout();
|
||||
let map_err = |io_error: io::Error| VmError::Io {
|
||||
error: io_error.kind(),
|
||||
position,
|
||||
let map_err = |io_error: io::Error| {
|
||||
VmError::NativeFunction(NativeFunctionError::Io {
|
||||
error: io_error.kind(),
|
||||
position,
|
||||
})
|
||||
};
|
||||
|
||||
let first_argument = to_register.saturating_sub(argument_count);
|
||||
@ -523,3 +531,42 @@ impl Display for NativeFunction {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum NativeFunctionError {
|
||||
ExpectedArgumentCount {
|
||||
expected: usize,
|
||||
found: usize,
|
||||
position: Span,
|
||||
},
|
||||
Panic {
|
||||
message: Option<String>,
|
||||
position: Span,
|
||||
},
|
||||
Parse {
|
||||
error: string::ParseError,
|
||||
position: Span,
|
||||
},
|
||||
Io {
|
||||
error: io::ErrorKind,
|
||||
position: Span,
|
||||
},
|
||||
}
|
||||
|
||||
impl AnnotatedError for NativeFunctionError {
|
||||
fn title() -> &'static str {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn description(&self) -> &'static str {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn details(&self) -> Option<String> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn position(&self) -> Span {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
use std::{cmp::Ordering, io, mem::replace};
|
||||
use std::{cmp::Ordering, mem::replace};
|
||||
|
||||
use crate::{
|
||||
parse, value::Primitive, AnnotatedError, Chunk, ChunkError, DustError, FunctionType,
|
||||
Identifier, Instruction, NativeFunction, Operation, Span, Type, Value, ValueError,
|
||||
Identifier, Instruction, NativeFunction, NativeFunctionError, Operation, Span, Type, Value,
|
||||
ValueError,
|
||||
};
|
||||
|
||||
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
|
||||
@ -636,10 +637,6 @@ pub enum VmError {
|
||||
found: Value,
|
||||
position: Span,
|
||||
},
|
||||
Panic {
|
||||
message: Option<String>,
|
||||
position: Span,
|
||||
},
|
||||
RegisterIndexOutOfBounds {
|
||||
index: usize,
|
||||
position: Span,
|
||||
@ -660,11 +657,8 @@ pub enum VmError {
|
||||
},
|
||||
|
||||
// Wrappers for foreign errors
|
||||
NativeFunction(NativeFunctionError),
|
||||
Chunk(ChunkError),
|
||||
Io {
|
||||
error: io::ErrorKind,
|
||||
position: Span,
|
||||
},
|
||||
Value {
|
||||
error: ValueError,
|
||||
position: Span,
|
||||
@ -688,14 +682,13 @@ impl AnnotatedError for VmError {
|
||||
Self::EmptyRegister { .. } => "Empty register",
|
||||
Self::ExpectedBoolean { .. } => "Expected boolean",
|
||||
Self::ExpectedFunction { .. } => "Expected function",
|
||||
Self::Panic { .. } => "Explicit Panic",
|
||||
Self::RegisterIndexOutOfBounds { .. } => "Register index out of bounds",
|
||||
Self::InvalidInstruction { .. } => "Invalid instruction",
|
||||
Self::StackOverflow { .. } => "Stack overflow",
|
||||
Self::StackUnderflow { .. } => "Stack underflow",
|
||||
Self::UndefinedVariable { .. } => "Undefined variable",
|
||||
Self::Chunk(error) => error.description(),
|
||||
Self::Io { .. } => "I/O error",
|
||||
Self::NativeFunction(error) => error.description(),
|
||||
Self::Value { .. } => "Value error",
|
||||
}
|
||||
}
|
||||
@ -704,7 +697,6 @@ impl AnnotatedError for VmError {
|
||||
match self {
|
||||
Self::EmptyRegister { index, .. } => Some(format!("Register {index} is empty")),
|
||||
Self::ExpectedFunction { found, .. } => Some(format!("{found} is not a function")),
|
||||
Self::Panic { message, .. } => message.clone(),
|
||||
Self::RegisterIndexOutOfBounds { index, .. } => {
|
||||
Some(format!("Register {index} does not exist"))
|
||||
}
|
||||
@ -712,7 +704,7 @@ impl AnnotatedError for VmError {
|
||||
Some(format!("{identifier} is not in scope"))
|
||||
}
|
||||
Self::Chunk(error) => error.details(),
|
||||
Self::Io { error, .. } => Some(error.to_string()),
|
||||
Self::NativeFunction(error) => error.details(),
|
||||
Self::Value { error, .. } => Some(error.to_string()),
|
||||
_ => None,
|
||||
}
|
||||
@ -724,14 +716,13 @@ impl AnnotatedError for VmError {
|
||||
Self::EmptyRegister { position, .. } => *position,
|
||||
Self::ExpectedBoolean { position, .. } => *position,
|
||||
Self::ExpectedFunction { position, .. } => *position,
|
||||
Self::Panic { position, .. } => *position,
|
||||
Self::RegisterIndexOutOfBounds { position, .. } => *position,
|
||||
Self::InvalidInstruction { position, .. } => *position,
|
||||
Self::StackUnderflow { position } => *position,
|
||||
Self::StackOverflow { position } => *position,
|
||||
Self::UndefinedVariable { position, .. } => *position,
|
||||
Self::Chunk(error) => error.position(),
|
||||
Self::Io { position, .. } => *position,
|
||||
Self::NativeFunction(error) => error.position(),
|
||||
Self::Value { position, .. } => *position,
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,10 @@ fn panic() {
|
||||
assert_eq!(
|
||||
run(source),
|
||||
Err(DustError::Runtime {
|
||||
error: VmError::Panic {
|
||||
error: VmError::NativeFunction(NativeFunctionError::Panic {
|
||||
message: Some("Goodbye world! 42".to_string()),
|
||||
position: Span(0, 27)
|
||||
},
|
||||
}),
|
||||
source
|
||||
})
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user