From 2c91cc4d051665cc61888e5ea6fde301a21e544a Mon Sep 17 00:00:00 2001 From: Doonv <58695417+doonv@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:35:04 +0200 Subject: [PATCH] Add isize and usize numbers, fix bugs --- src/builtin_parser/lexer.rs | 2 ++ src/builtin_parser/number.rs | 21 +++++++++++++++++++++ src/builtin_parser/parser.rs | 3 ++- src/builtin_parser/runner.rs | 3 ++- src/builtin_parser/runner/error.rs | 1 + src/builtin_parser/runner/unique_rc.rs | 25 ++++++++++--------------- src/builtin_parser/runner/value.rs | 11 +++++++---- src/command.rs | 8 +++----- src/config.rs | 2 ++ 9 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/builtin_parser/lexer.rs b/src/builtin_parser/lexer.rs index 90b8a6f..1c7f638 100644 --- a/src/builtin_parser/lexer.rs +++ b/src/builtin_parser/lexer.rs @@ -76,10 +76,12 @@ pub enum Token { #[token("i16")] #[token("i32")] #[token("i64")] + #[token("isize")] #[token("u8")] #[token("u16")] #[token("u32")] #[token("u64")] + #[token("usize")] #[token("f32")] #[token("f64")] NumberType, diff --git a/src/builtin_parser/number.rs b/src/builtin_parser/number.rs index cea88ef..46f94ad 100644 --- a/src/builtin_parser/number.rs +++ b/src/builtin_parser/number.rs @@ -23,10 +23,14 @@ pub enum Number { u16(u16), u32(u32), u64(u64), + usize(usize), + i8(i8), i16(i16), i32(i32), i64(i64), + isize(isize), + f32(f32), f64(f64), } @@ -39,10 +43,12 @@ impl Number { Number::u16(number) => Box::new(number), Number::u32(number) => Box::new(number), Number::u64(number) => Box::new(number), + Number::usize(number) => Box::new(number), Number::i8(number) => Box::new(number), Number::i16(number) => Box::new(number), Number::i32(number) => Box::new(number), Number::i64(number) => Box::new(number), + Number::isize(number) => Box::new(number), Number::f32(number) => Box::new(number), Number::f64(number) => Box::new(number), Number::Integer(_) => todo!(), @@ -59,10 +65,12 @@ impl Number { Number::u16(_) => "a u16", Number::u32(_) => "a u32", Number::u64(_) => "a u64", + Number::usize(_) => "a usize", Number::i8(_) => "a i8", Number::i16(_) => "a i16", Number::i32(_) => "a i32", Number::i64(_) => "a i64", + Number::isize(_) => "a usize", Number::f32(_) => "a f32", Number::f64(_) => "a f64", } @@ -78,10 +86,12 @@ impl Display for Number { Number::u16(number) => write!(f, "{number} (u16)"), Number::u32(number) => write!(f, "{number} (u32)"), Number::u64(number) => write!(f, "{number} (u64)"), + Number::usize(number) => write!(f, "{number} (usize)"), Number::i8(number) => write!(f, "{number} (i8)"), Number::i16(number) => write!(f, "{number} (i16)"), Number::i32(number) => write!(f, "{number} (i32)"), Number::i64(number) => write!(f, "{number} (i64)"), + Number::isize(number) => write!(f, "{number} (isize)"), Number::f32(number) => write!(f, "{number} (f32)"), Number::f64(number) => write!(f, "{number} (f64)"), } @@ -98,10 +108,12 @@ macro_rules! impl_op { (Number::u16(left), Number::u16(right)) => Ok(Number::u16(left $op right)), (Number::u32(left), Number::u32(right)) => Ok(Number::u32(left $op right)), (Number::u64(left), Number::u64(right)) => Ok(Number::u64(left $op right)), + (Number::usize(left), Number::usize(right)) => Ok(Number::usize(left $op right)), (Number::i8(left), Number::i8(right)) => Ok(Number::i8(left $op right)), (Number::i16(left), Number::i16(right)) => Ok(Number::i16(left $op right)), (Number::i32(left), Number::i32(right)) => Ok(Number::i32(left $op right)), (Number::i64(left), Number::i64(right)) => Ok(Number::i64(left $op right)), + (Number::isize(left), Number::isize(right)) => Ok(Number::isize(left $op right)), (Number::f32(left), Number::f32(right)) => Ok(Number::f32(left $op right)), (Number::f64(left), Number::f64(right)) => Ok(Number::f64(left $op right)), @@ -109,19 +121,23 @@ macro_rules! impl_op { (Number::Integer(left), Number::u16(right)) => Ok(Number::u16(left as u16 $op right)), (Number::Integer(left), Number::u32(right)) => Ok(Number::u32(left as u32 $op right)), (Number::Integer(left), Number::u64(right)) => Ok(Number::u64(left as u64 $op right)), + (Number::Integer(left), Number::usize(right)) => Ok(Number::usize(left as usize $op right)), (Number::Integer(left), Number::i8(right)) => Ok(Number::i8(left as i8 $op right)), (Number::Integer(left), Number::i16(right)) => Ok(Number::i16(left as i16 $op right)), (Number::Integer(left), Number::i32(right)) => Ok(Number::i32(left as i32 $op right)), (Number::Integer(left), Number::i64(right)) => Ok(Number::i64(left as i64 $op right)), + (Number::Integer(left), Number::isize(right)) => Ok(Number::isize(left as isize $op right)), (Number::Integer(left), Number::Integer(right)) => Ok(Number::Integer(left $op right)), (Number::u8(left), Number::Integer(right)) => Ok(Number::u8(left $op right as u8)), (Number::u16(left), Number::Integer(right)) => Ok(Number::u16(left $op right as u16)), (Number::u32(left), Number::Integer(right)) => Ok(Number::u32(left $op right as u32)), (Number::u64(left), Number::Integer(right)) => Ok(Number::u64(left $op right as u64)), + (Number::usize(left), Number::Integer(right)) => Ok(Number::usize(left $op right as usize)), (Number::i8(left), Number::Integer(right)) => Ok(Number::i8(left $op right as i8)), (Number::i16(left), Number::Integer(right)) => Ok(Number::i16(left $op right as i16)), (Number::i32(left), Number::Integer(right)) => Ok(Number::i32(left $op right as i32)), (Number::i64(left), Number::Integer(right)) => Ok(Number::i64(left $op right as i64)), + (Number::isize(left), Number::Integer(right)) => Ok(Number::isize(left $op right as isize)), (Number::Float(left), Number::f32(right)) => Ok(Number::f32(left as f32 $op right)), (Number::Float(left), Number::f64(right)) => Ok(Number::f64(left as f64 $op right)), @@ -183,10 +199,15 @@ impl Number { span, value: self, })), + Number::usize(_) => Err(RunError::CannotNegateUnsignedInteger(Spanned { + span, + value: self, + })), Number::i8(number) => Ok(Number::i8(-number)), Number::i16(number) => Ok(Number::i16(-number)), Number::i32(number) => Ok(Number::i32(-number)), Number::i64(number) => Ok(Number::i64(-number)), + Number::isize(number) => Ok(Number::isize(-number)), Number::f32(number) => Ok(Number::f32(-number)), Number::f64(number) => Ok(Number::f64(-number)), Number::Float(number) => Ok(Number::Float(-number)), diff --git a/src/builtin_parser/parser.rs b/src/builtin_parser/parser.rs index f22c8d3..25d3cbb 100644 --- a/src/builtin_parser/parser.rs +++ b/src/builtin_parser/parser.rs @@ -320,10 +320,11 @@ fn parse_primary( "u16" => Number::u16(tokens.slice().parse().map_err(err_map)?), "u32" => Number::u32(tokens.slice().parse().map_err(err_map)?), "u64" => Number::u64(tokens.slice().parse().map_err(err_map)?), + "usize" => Number::usize(tokens.slice().parse().map_err(err_map)?), "i8" => Number::i8(tokens.slice().parse().map_err(err_map)?), "i16" => Number::i16(tokens.slice().parse().map_err(err_map)?), "i32" => Number::i32(tokens.slice().parse().map_err(err_map)?), - "i64" => Number::i64(tokens.slice().parse().map_err(err_map)?), + "isize" => Number::isize(tokens.slice().parse().map_err(err_map)?), "f32" => Number::f32(tokens.slice().parse().unwrap()), "f64" => Number::f64(tokens.slice().parse().unwrap()), _ => unreachable!(), diff --git a/src/builtin_parser/runner.rs b/src/builtin_parser/runner.rs index e6e5ac3..b261ac8 100644 --- a/src/builtin_parser/runner.rs +++ b/src/builtin_parser/runner.rs @@ -14,7 +14,7 @@ use self::{ use super::{ parser::{Ast, Expression, Operator}, - Number, SpanExtension, Spanned, + Number, Spanned, }; use bevy::{ prelude::*, @@ -132,6 +132,7 @@ fn eval_expression( registrations, }, )?; + *variable.upgrade().unwrap().borrow_mut() = value; Ok(Value::Reference(variable)) diff --git a/src/builtin_parser/runner/error.rs b/src/builtin_parser/runner/error.rs index 57c9ec5..9ecac18 100644 --- a/src/builtin_parser/runner/error.rs +++ b/src/builtin_parser/runner/error.rs @@ -52,6 +52,7 @@ pub enum RunError { } impl RunError { + /// Get all the locations of the error in the source. pub fn spans(&self) -> Vec { use RunError::*; diff --git a/src/builtin_parser/runner/unique_rc.rs b/src/builtin_parser/runner/unique_rc.rs index d50568e..e20a6c9 100644 --- a/src/builtin_parser/runner/unique_rc.rs +++ b/src/builtin_parser/runner/unique_rc.rs @@ -22,9 +22,10 @@ impl UniqueRc { unsafe fn get_rc(&self) -> &Rc> { &self.0 } - pub fn borrow_inner(&self) -> &RefCell { + pub(crate) fn borrow_inner(&self) -> &RefCell { &self.0 } + /// Create a new weak pointer to this [`UniqueRc`]. pub fn borrow(&self) -> WeakRef { WeakRef::new(self) } @@ -34,6 +35,7 @@ impl UniqueRc { pub fn new(value: T) -> UniqueRc { UniqueRc(Rc::new(RefCell::new(value))) } + /// Get the inner value (`T`) of this [`UniqueRc`]. pub fn into_inner(self) -> T { Rc::try_unwrap(self.0) .unwrap_or_else(|rc| { @@ -58,10 +60,10 @@ impl DerefMut for UniqueRc { } } +/// A weak reference to a [`UniqueRc`] may or may not exist. #[derive(Debug)] pub struct WeakRef { reference: Weak>, - upgraded: Cell, } impl WeakRef { fn new(unique_rc: &UniqueRc) -> Self { @@ -69,32 +71,25 @@ impl WeakRef { let rc = unsafe { unique_rc.get_rc() }; Self { reference: Rc::downgrade(rc), - upgraded: Cell::new(false), } } + /// Converts this [`WeakRef`] into a [`StrongRef`] (may be unsafe, see [`StrongRef`]'s documentation). pub fn upgrade(&self) -> Option> { - if !self.upgraded.get() { - self.upgraded.set(true); - unsafe { self.upgrade_unchecked() } - } else { - None - } - } - unsafe fn upgrade_unchecked(&self) -> Option> { Some(StrongRef(self.reference.upgrade()?)) } } -/// A reference to value `T`. +/// A strong reference to value `T`. /// -/// This value is *technically* unsafe, but in practice the only way -/// you could obtain it is by having it passed into a custom function. +/// This value is *technically* unsafe due to [`UniqueRc`] expecting only one strong reference to its inner value. +/// However in practice the only way you could obtain it is by having it passed into a custom function. +/// In which case it is safe (probably). /// /// ``` /// use bevy_dev_console::builtin_parser::{Value, StrongRef}; /// /// fn add_to_reference(my_reference: StrongRef, add: String) { -/// // currently you can only do it with `Value` +/// // currently you can only do it with `Value` (TODO) /// if let Value::String(string) = &mut *my_reference.borrow_mut() { /// *string += &add; /// } else { diff --git a/src/builtin_parser/runner/value.rs b/src/builtin_parser/runner/value.rs index f5c137b..1dc7a98 100644 --- a/src/builtin_parser/runner/value.rs +++ b/src/builtin_parser/runner/value.rs @@ -32,10 +32,11 @@ pub enum Value { /// A reference. /// /// References are very similar to rust's ownership and borrowing. - /// We achieve this by storing every variable as a [`Rc>`], - /// and having only the owner of the value have a strong reference, + /// We achieve this by storing every variable as a [`UniqueRc`](super::unique_rc::UniqueRc) + /// (which is essentially just [`Rc>`] + /// but having only the owner of the value have a strong reference, /// while every other value has a weak reference. This causes - /// [`Rc::try_unwrap`] to succeed every time. + /// [`Rc::try_unwrap`] to succeed every time) Reference(WeakRef), /// A dynamic [`HashMap`]. Object(HashMap>>), @@ -132,6 +133,8 @@ impl Value { } } + /// Returns the kind of [`Value`] as a [string slice](str). + /// Used for more natural sounding error messages. pub fn kind(&self) -> &'static str { match self { Value::None => "nothing", @@ -403,7 +406,7 @@ macro_rules! impl_function_param_for_numbers { } impl_function_param_for_numbers!(Float(f32, f64)); -impl_function_param_for_numbers!(Integer(u8, u16, u32, u64, i8, i16, i32, i64)); +impl_function_param_for_numbers!(Integer(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize)); impl_function_param_for_value!(impl bool: Value::Boolean(boolean) => boolean); impl_function_param_for_value!(impl Number: Value::Number(number) => number); diff --git a/src/command.rs b/src/command.rs index 5ab07ed..53a0097 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,9 +1,6 @@ //! Command execution functionality. -use std::{ - borrow::Cow, - ops::{Bound, Range, RangeBounds}, -}; +use std::{borrow::Cow, ops::Range}; use bevy::{ecs::system::Command, prelude::*}; @@ -40,6 +37,7 @@ pub struct CommandHint { pub description: Cow<'static, str>, } impl CommandHint { + /// Creates a new [`CommandHint`]. pub fn new( span: Range, color: CommandHintColor, @@ -102,11 +100,11 @@ impl CommandHints { pub(crate) fn reset_hint_added(&mut self) { if self.hint_added { dbg!("yeah"); - self.hint_added = false; } else { dbg!("nah"); self.push([]); } + self.hint_added = false; } } diff --git a/src/config.rs b/src/config.rs index d602e08..8a53f89 100644 --- a/src/config.rs +++ b/src/config.rs @@ -111,6 +111,7 @@ impl ConsoleTheme { } } + /// Returns a [`TextFormat`] with a color based on the [`Level`] and the [`ConsoleTheme`]. pub fn format_level(&self, level: Level) -> TextFormat { TextFormat { color: self.color_level(level), @@ -118,6 +119,7 @@ impl ConsoleTheme { } } + /// Returns a [`TextFormat`] with the default font and color. pub fn format_text(&self) -> TextFormat { TextFormat { font_id: self.font.clone(),