Skip to content

Commit

Permalink
Add isize and usize numbers, fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
doonv committed Jan 3, 2024
1 parent 759b484 commit 2c91cc4
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 26 deletions.
2 changes: 2 additions & 0 deletions src/builtin_parser/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
21 changes: 21 additions & 0 deletions src/builtin_parser/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
Expand All @@ -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!(),
Expand All @@ -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",
}
Expand All @@ -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)"),
}
Expand All @@ -98,30 +108,36 @@ 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)),

(Number::Integer(left), Number::u8(right)) => Ok(Number::u8(left as u8 $op right)),
(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)),
Expand Down Expand Up @@ -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)),
Expand Down
3 changes: 2 additions & 1 deletion src/builtin_parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(),
Expand Down
3 changes: 2 additions & 1 deletion src/builtin_parser/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use self::{

use super::{
parser::{Ast, Expression, Operator},
Number, SpanExtension, Spanned,
Number, Spanned,
};
use bevy::{
prelude::*,
Expand Down Expand Up @@ -132,6 +132,7 @@ fn eval_expression(
registrations,
},
)?;

*variable.upgrade().unwrap().borrow_mut() = value;

Ok(Value::Reference(variable))
Expand Down
1 change: 1 addition & 0 deletions src/builtin_parser/runner/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub enum RunError {
}

impl RunError {
/// Get all the locations of the error in the source.
pub fn spans(&self) -> Vec<Span> {
use RunError::*;

Expand Down
25 changes: 10 additions & 15 deletions src/builtin_parser/runner/unique_rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ impl<T: ?Sized> UniqueRc<T> {
unsafe fn get_rc(&self) -> &Rc<RefCell<T>> {
&self.0
}
pub fn borrow_inner(&self) -> &RefCell<T> {
pub(crate) fn borrow_inner(&self) -> &RefCell<T> {
&self.0
}
/// Create a new weak pointer to this [`UniqueRc`].
pub fn borrow(&self) -> WeakRef<T> {
WeakRef::new(self)
}
Expand All @@ -34,6 +35,7 @@ impl<T> UniqueRc<T> {
pub fn new(value: T) -> UniqueRc<T> {
UniqueRc(Rc::new(RefCell::new(value)))
}
/// Get the inner value (`T`) of this [`UniqueRc<T>`].
pub fn into_inner(self) -> T {
Rc::try_unwrap(self.0)
.unwrap_or_else(|rc| {
Expand All @@ -58,43 +60,36 @@ impl<T> DerefMut for UniqueRc<T> {
}
}

/// A weak reference to a [`UniqueRc`] may or may not exist.
#[derive(Debug)]
pub struct WeakRef<T: ?Sized> {
reference: Weak<RefCell<T>>,
upgraded: Cell<bool>,
}
impl<T: ?Sized> WeakRef<T> {
fn new(unique_rc: &UniqueRc<T>) -> Self {
// SAFETY: We are not cloning the `Rc`, so this is fine.
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<StrongRef<T>> {
if !self.upgraded.get() {
self.upgraded.set(true);
unsafe { self.upgrade_unchecked() }
} else {
None
}
}
unsafe fn upgrade_unchecked(&self) -> Option<StrongRef<T>> {
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<Value>, 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 {
Expand Down
11 changes: 7 additions & 4 deletions src/builtin_parser/runner/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<RefCell<Value>>`],
/// and having only the owner of the value have a strong reference,
/// We achieve this by storing every variable as a [`UniqueRc<T>`](super::unique_rc::UniqueRc)
/// (which is essentially just [`Rc<RefCell<T>>`]
/// 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<Value>),
/// A dynamic [`HashMap`].
Object(HashMap<String, Rc<RefCell<Value>>>),
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 3 additions & 5 deletions src/command.rs
Original file line number Diff line number Diff line change
@@ -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::*};

Expand Down Expand Up @@ -40,6 +37,7 @@ pub struct CommandHint {
pub description: Cow<'static, str>,
}
impl CommandHint {
/// Creates a new [`CommandHint`].
pub fn new(
span: Range<usize>,
color: CommandHintColor,
Expand Down Expand Up @@ -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;
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,15 @@ 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),
..self.format_text()
}
}

/// Returns a [`TextFormat`] with the default font and color.
pub fn format_text(&self) -> TextFormat {
TextFormat {
font_id: self.font.clone(),
Expand Down

0 comments on commit 2c91cc4

Please sign in to comment.