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