From 6827cdd217928282db7dfa88cbdcca49811722c3 Mon Sep 17 00:00:00 2001 From: Doonv <58695417+doonv@users.noreply.github.com> Date: Mon, 1 Jan 2024 15:07:39 +0200 Subject: [PATCH] Replace more `todo!`s with errors --- examples/custom_functions.rs | 6 ++-- src/builtin_parser.rs | 3 ++ src/builtin_parser/number.rs | 24 ++++++------- src/builtin_parser/runner/environment.rs | 5 ++- src/builtin_parser/runner/error.rs | 13 +++++++ src/builtin_parser/runner/value.rs | 44 ++++++++++++++++-------- src/command.rs | 7 ++-- src/ui.rs | 3 +- 8 files changed, 70 insertions(+), 35 deletions(-) diff --git a/examples/custom_functions.rs b/examples/custom_functions.rs index 370a79f..3254309 100644 --- a/examples/custom_functions.rs +++ b/examples/custom_functions.rs @@ -20,8 +20,10 @@ fn time_since_epoch() { info!("The unix epoch was {} seconds ago", time.as_secs()); } -/// Function with parameters and return value -fn add(num1: Spanned, num2: Spanned) -> Result { +/// Function with parameters and return value. +/// +/// Note that this will cause an error if an integer to passed to this function. +fn add(num1: f64, num2: f64) -> f64 { num1 + num2 } diff --git a/src/builtin_parser.rs b/src/builtin_parser.rs index ffcb7f0..c7bc222 100644 --- a/src/builtin_parser.rs +++ b/src/builtin_parser.rs @@ -19,8 +19,11 @@ pub(crate) mod runner; pub use number::*; pub use runner::{environment::Environment, error::RunError, unique_rc::*, Value}; +/// Additonal traits for span. pub trait SpanExtension { + /// Wrap this value with a [`Spanned`]. fn wrap(self, value: T) -> Spanned; + /// Combine two [`Span`]s into one. fn join(self, span: Self) -> Self; } impl SpanExtension for Span { diff --git a/src/builtin_parser/number.rs b/src/builtin_parser/number.rs index 1d849b7..cea88ef 100644 --- a/src/builtin_parser/number.rs +++ b/src/builtin_parser/number.rs @@ -53,18 +53,18 @@ impl Number { /// Returns a [`&'static str`](str) represents the kind of the number. pub fn kind(&self) -> &'static str { match self { - Number::Float(_) => "(float)", - Number::Integer(_) => "(integer)", - Number::u8(_) => "u8", - Number::u16(_) => "u16", - Number::u32(_) => "u32", - Number::u64(_) => "u64", - Number::i8(_) => "i8", - Number::i16(_) => "i16", - Number::i32(_) => "i32", - Number::i64(_) => "i64", - Number::f32(_) => "f32", - Number::f64(_) => "f64", + Number::Float(_) => "a float", + Number::Integer(_) => "an integer", + Number::u8(_) => "a u8", + Number::u16(_) => "a u16", + Number::u32(_) => "a u32", + Number::u64(_) => "a u64", + Number::i8(_) => "a i8", + Number::i16(_) => "a i16", + Number::i32(_) => "a i32", + Number::i64(_) => "a i64", + Number::f32(_) => "a f32", + Number::f64(_) => "a f64", } } } diff --git a/src/builtin_parser/runner/environment.rs b/src/builtin_parser/runner/environment.rs index 28a161c..1a396b8 100644 --- a/src/builtin_parser/runner/environment.rs +++ b/src/builtin_parser/runner/environment.rs @@ -154,8 +154,7 @@ macro_rules! impl_into_function { world, environment, registrations - ) - .unwrap_or_else(|_| todo!()); + )?; res }),+)? @@ -320,7 +319,7 @@ impl Environment { /// Registers a function for use inside the language. /// - /// All parameters must implement [`TryFrom`]. + /// All parameters must implement [`FunctionParam`]. /// There is a limit of 8 parameters. /// /// The return value of the function must implement [`Into`] diff --git a/src/builtin_parser/runner/error.rs b/src/builtin_parser/runner/error.rs index 2066204..57c9ec5 100644 --- a/src/builtin_parser/runner/error.rs +++ b/src/builtin_parser/runner/error.rs @@ -11,6 +11,7 @@ use super::Value; /// An error occuring during the while executing the [`AST`](Ast) of the command. #[derive(Debug)] +#[allow(missing_docs)] pub enum RunError { /// A custom text message. Contains very little contextual information, try to find an existing error instead. Custom { @@ -43,6 +44,11 @@ pub enum RunError { right: &'static str, span: Span, }, + IncompatibleFunctionParameter { + expected: &'static str, + actual: &'static str, + span: Span, + }, } impl RunError { @@ -65,6 +71,7 @@ impl RunError { CannotMoveOutOfResource(Spanned { span, .. }) => vec![span.clone()], CannotNegateUnsignedInteger(Spanned { span, .. }) => vec![span.clone()], IncompatibleNumberTypes { span, .. } => vec![span.clone()], + IncompatibleFunctionParameter { span, .. } => vec![span.clone()], } } pub fn hints(&self) -> Vec { @@ -109,6 +116,12 @@ impl RunError { format!("Incompatible number types; `{left}` and `{right}` are incompatible.") .into() } + IncompatibleFunctionParameter { + expected, actual, .. + } => { + format!("Mismatched function paramater type. Expected {expected} but got {actual}") + .into() + } } } } diff --git a/src/builtin_parser/runner/value.rs b/src/builtin_parser/runner/value.rs index 980f739..f5c137b 100644 --- a/src/builtin_parser/runner/value.rs +++ b/src/builtin_parser/runner/value.rs @@ -135,7 +135,7 @@ impl Value { pub fn kind(&self) -> &'static str { match self { Value::None => "nothing", - Value::Number(_) => "a number", + Value::Number(number) => number.kind(), Value::Boolean(_) => "a boolean", Value::String(_) => "a string", Value::Reference(_) => "a reference", @@ -290,7 +290,7 @@ impl FunctionParam for Spanned { Ok(value.unwrap()) } } -impl> FunctionParam for Spanned { +impl, Error = RunError>> FunctionParam for Spanned { type Item<'world, 'env, 'reg> = Self; const USES_VALUE: bool = true; @@ -302,8 +302,8 @@ impl> FunctionParam for Spanned { ) -> Result, RunError> { let value = value.unwrap(); Ok(Spanned { - span: value.span, - value: T::try_from(value.value)?, + span: value.span.clone(), + value: T::try_from(value)?, }) } } @@ -333,18 +333,23 @@ macro_rules! impl_function_param_for_value { _: &mut Option<&'env mut Environment>, _: &'reg [&'reg TypeRegistration], ) -> Result, RunError> { - if let $value_pattern = value.unwrap().value { + let value = value.unwrap(); + if let $value_pattern = value.value { Ok($return) } else { - todo!() + Err(RunError::IncompatibleFunctionParameter { + expected: stringify!($type), + actual: value.value.kind(), + span: value.span, + }) } } } - impl TryFrom for $type { + impl TryFrom> for $type { type Error = RunError; - fn try_from(value: Value) -> Result { - if let $value_pattern = value { + fn try_from(value: Spanned) -> Result { + if let $value_pattern = value.value { Ok($return) } else { todo!() @@ -366,21 +371,30 @@ macro_rules! impl_function_param_for_numbers { _: &mut Option<&'env mut Environment>, _: &'reg [&'reg TypeRegistration], ) -> Result, RunError> { - match value.unwrap().value { + let value = value.unwrap(); + match value.value { Value::Number(Number::$number(value)) => Ok(value), Value::Number(Number::$generic(value)) => Ok(value as $number), - _ => todo!() + _ => Err(RunError::IncompatibleFunctionParameter { + expected: concat!("a ", stringify!($number)), + actual: value.value.kind(), + span: value.span, + }) } } } - impl TryFrom for $number { + impl TryFrom> for $number { type Error = RunError; - fn try_from(value: Value) -> Result { - match value { + fn try_from(value: Spanned) -> Result { + match value.value { Value::Number(Number::$number(value)) => Ok(value), Value::Number(Number::$generic(value)) => Ok(value as $number), - _ => todo!() + _ => Err(RunError::IncompatibleFunctionParameter { + expected: concat!("a ", stringify!($number)), + actual: value.value.kind(), + span: value.span + }) } } } diff --git a/src/command.rs b/src/command.rs index 92ad1a1..5ab07ed 100644 --- a/src/command.rs +++ b/src/command.rs @@ -79,7 +79,7 @@ pub enum CommandHintColor { /// A resource where hints (errors/warnings/etc) are stored /// to be displayed in the developer console. -#[derive(Resource, Default, Deref)] +#[derive(Resource, Debug, Default, Deref)] pub struct CommandHints { #[deref] hints: Vec>, @@ -95,13 +95,16 @@ impl CommandHints { hints.into() ) } else { + self.hint_added = true; self.hints.push(hints.into()); } } pub(crate) fn reset_hint_added(&mut self) { if self.hint_added { + dbg!("yeah"); self.hint_added = false; } else { + dbg!("nah"); self.push([]); } } @@ -121,7 +124,7 @@ impl CommandHints { /// fn parse(&self, command: &str, world: &mut World) { /// // The `name: COMMAND_RESULT_NAME` tells the console this is a result from /// // the parser and then formats it accordingly. -/// // TODO: figure out better solution for this +/// # // TODO: figure out better solution for this /// info!(name: COMMAND_RESULT_NAME, "You just entered the command {command}") /// } /// } diff --git a/src/ui.rs b/src/ui.rs index 6d33ec1..e3dac1c 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -215,6 +215,8 @@ fn format_line( } let hints = &hints[*command_index]; + *command_index += 1; + // TODO: Handle more than just he first element if let Some(hint) = hints.first() { const PREFIX_LEN: usize = COMMAND_MESSAGE_PREFIX.len(); @@ -239,7 +241,6 @@ fn format_line( ); return text; } - *command_index += 1; } text.append(message.as_str(), 0.0, config.theme.format_text());