Skip to content

Commit

Permalink
Add typeof function
Browse files Browse the repository at this point in the history
  • Loading branch information
doonv committed Jan 17, 2024
1 parent b824c0e commit 9baf343
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 12 deletions.
29 changes: 26 additions & 3 deletions src/builtin_parser/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,31 @@ impl Number {
}
}

/// Returns a [`&'static str`](str) represents the kind of the number.
/// Returns the kind of [`Number`] as a [string slice](str).
/// You may want to use [`natural_kind`](Self::natural_kind)
/// instead for more natural sounding error messsages
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::usize(_) => "usize",
Number::i8(_) => "i8",
Number::i16(_) => "i16",
Number::i32(_) => "i32",
Number::i64(_) => "i64",
Number::isize(_) => "usize",
Number::f32(_) => "f32",
Number::f64(_) => "f64",
}
}

/// Returns the kind of [`Number`] as a [string slice](str) with an `a` or `an` prepended to it.
/// Used for more natural sounding error messages.
pub fn natural_kind(&self) -> &'static str {
match self {
Number::Float(_) => "a float",
Number::Integer(_) => "an integer",
Expand Down Expand Up @@ -167,8 +190,8 @@ macro_rules! impl_op {
(Number::f32(left), Number::Float(right)) => Ok(Number::f32(left $op right as f32)),
(Number::f64(left), Number::Float(right)) => Ok(Number::f64(left $op right as f64)),
_ => Err(RunError::IncompatibleNumberTypes {
left: left.kind(),
right: right.kind(),
left: left.natural_kind(),
right: right.natural_kind(),
span
})
}
Expand Down
7 changes: 5 additions & 2 deletions src/builtin_parser/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ fn eval_expression(
},
)?;

*variable.upgrade().unwrap().borrow_mut() = value;
match variable.upgrade() {
Some(strong) => *strong.borrow_mut() = value,
None => todo_error!("cannot "),
}

Ok(Value::Reference(variable))
}
Expand Down Expand Up @@ -664,7 +667,7 @@ fn eval_path(
Ok(expr.span.wrap(Path::Variable(reference.clone())))
} else {
Err(RunError::CannotDereferenceValue(
expr.span.wrap(borrow.kind()),
expr.span.wrap(borrow.natural_kind()),
))
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/builtin_parser/runner/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl RunError {
}
ExpectedNumberAfterUnaryOperator(Spanned { value, .. }) => format!(
"Expected a number after unary operator (-) but got {} instead.",
value.kind()
value.natural_kind()
)
.into(),
CannotIndexValue(_) => todo!(),
Expand Down Expand Up @@ -144,7 +144,7 @@ impl RunError {
}
CannotNegateUnsignedInteger(Spanned { value, .. }) => format!(
"Unsigned integers cannot be negated. (Type: {})",
value.kind()
value.natural_kind()
)
.into(),
IncompatibleNumberTypes { left, right, .. } => {
Expand Down
5 changes: 5 additions & 0 deletions src/builtin_parser/runner/stdlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ fn print_env(env: &mut Environment) {
}
}

fn typeof_value(value: Value) -> String {
value.kind().to_string()
}

/// Disposes of a [`Value`].
fn drop(_: Value) {}

Expand All @@ -78,5 +82,6 @@ pub fn register(environment: &mut Environment) {
fn ref_depth;
fn drop;
fn print_env;
fn typeof_value as "typeof";
});
}
28 changes: 23 additions & 5 deletions src/builtin_parser/runner/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,29 @@ impl Value {
}

/// Returns the kind of [`Value`] as a [string slice](str).
/// Used for more natural sounding error messages.
/// You may want to use [`natural_kind`](Self::natural_kind)
/// instead for more natural sounding error messsages
pub fn kind(&self) -> &'static str {
match self {
Value::None => "nothing",
Value::None => "none",
Value::Number(number) => number.kind(),
Value::Boolean(..) => "boolean",
Value::String(..) => "string",
Value::Reference(..) => "reference",
Value::Object(..) => "object",
Value::StructObject { .. } => "struct object",
Value::Tuple(..) => "tuple",
Value::StructTuple { .. } => "struct tuple",
Value::Resource(..) => "resource",
}
}

/// Returns the kind of [`Value`] as a [string slice](str) with an `a` or `an` prepended to it.
/// Used for more natural sounding error messages.
pub fn natural_kind(&self) -> &'static str {
match self {
Value::None => "nothing",
Value::Number(number) => number.natural_kind(),
Value::Boolean(..) => "a boolean",
Value::String(..) => "a string",
Value::Reference(..) => "a reference",
Expand Down Expand Up @@ -482,7 +500,7 @@ macro_rules! impl_function_param_for_value {
} else {
Err(RunError::IncompatibleFunctionParameter {
expected: stringify!($type),
actual: value.value.kind(),
actual: value.value.natural_kind(),
span: value.span,
})
}
Expand Down Expand Up @@ -520,7 +538,7 @@ macro_rules! impl_function_param_for_numbers {
Value::Number(Number::$generic(value)) => Ok(value as $number),
_ => Err(RunError::IncompatibleFunctionParameter {
expected: concat!("a ", stringify!($number)),
actual: value.value.kind(),
actual: value.value.natural_kind(),
span: value.span,
})
}
Expand All @@ -535,7 +553,7 @@ macro_rules! impl_function_param_for_numbers {
Value::Number(Number::$generic(value)) => Ok(value as $number),
_ => Err(RunError::IncompatibleFunctionParameter {
expected: concat!("a ", stringify!($number)),
actual: value.value.kind(),
actual: value.value.natural_kind(),
span: value.span
})
}
Expand Down

0 comments on commit 9baf343

Please sign in to comment.