diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 7ccee98..9f6f99d 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -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}; diff --git a/dust-lang/src/native_function.rs b/dust-lang/src/native_function.rs index 872e9fe..69d04b6 100644 --- a/dust-lang/src/native_function.rs +++ b/dust-lang/src/native_function.rs @@ -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, + 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 { + todo!() + } + + fn position(&self) -> Span { + todo!() + } +} diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 500764f..dab2bbc 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -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, DustError> { @@ -636,10 +637,6 @@ pub enum VmError { found: Value, position: Span, }, - Panic { - message: Option, - 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, } } diff --git a/dust-lang/tests/native_functions.rs b/dust-lang/tests/native_functions.rs index 307477f..7921649 100644 --- a/dust-lang/tests/native_functions.rs +++ b/dust-lang/tests/native_functions.rs @@ -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 }) )