interpreter: Add float machinery

- operators
- type casting
This commit is contained in:
John 2024-09-18 01:02:09 -05:00
parent 0f8b0824ac
commit fad28beb05
3 changed files with 18 additions and 2 deletions

View File

@ -223,6 +223,7 @@ builtins! {
Ok(match tail { Ok(match tail {
ConValue::Empty => ConValue::Empty, ConValue::Empty => ConValue::Empty,
ConValue::Int(v) => ConValue::Int(v.wrapping_neg()), ConValue::Int(v) => ConValue::Int(v.wrapping_neg()),
ConValue::Float(v) => ConValue::Float(-v),
_ => Err(Error::TypeError)?, _ => Err(Error::TypeError)?,
}) })
} }

View File

@ -20,6 +20,8 @@ pub enum ConValue {
Empty, Empty,
/// An integer /// An integer
Int(Integer), Int(Integer),
/// A floating point number
Float(f64),
/// A boolean /// A boolean
Bool(bool), Bool(bool),
/// A unicode character /// A unicode character
@ -124,6 +126,7 @@ macro cmp ($($fn:ident: $empty:literal, $op:tt);*$(;)?) {$(
match (self, other) { match (self, other) {
(Self::Empty, Self::Empty) => Ok(Self::Bool($empty)), (Self::Empty, Self::Empty) => Ok(Self::Bool($empty)),
(Self::Int(a), Self::Int(b)) => Ok(Self::Bool(a $op b)), (Self::Int(a), Self::Int(b)) => Ok(Self::Bool(a $op b)),
(Self::Float(a), Self::Float(b)) => Ok(Self::Bool(a $op b)),
(Self::Bool(a), Self::Bool(b)) => Ok(Self::Bool(a $op b)), (Self::Bool(a), Self::Bool(b)) => Ok(Self::Bool(a $op b)),
(Self::Char(a), Self::Char(b)) => Ok(Self::Bool(a $op b)), (Self::Char(a), Self::Char(b)) => Ok(Self::Bool(a $op b)),
(Self::String(a), Self::String(b)) => Ok(Self::Bool(&**a $op &**b)), (Self::String(a), Self::String(b)) => Ok(Self::Bool(&**a $op &**b)),
@ -150,6 +153,7 @@ impl From<&Sym> for ConValue {
} }
from! { from! {
Integer => ConValue::Int, Integer => ConValue::Int,
f64 => ConValue::Float,
bool => ConValue::Bool, bool => ConValue::Bool,
char => ConValue::Char, char => ConValue::Char,
Sym => ConValue::String, Sym => ConValue::String,
@ -189,7 +193,8 @@ ops! {
Add: add = [ Add: add = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_add(b)), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_add(b)),
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &b.to_string()).into(), (ConValue::Float(a), ConValue::Float(b)) => ConValue::Float(a + b),
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &*b).into(),
(ConValue::String(s), ConValue::Char(c)) => { let mut s = s.to_string(); s.push(c); s.into() } (ConValue::String(s), ConValue::Char(c)) => { let mut s = s.to_string(); s.push(c); s.into() }
(ConValue::Char(a), ConValue::Char(b)) => { (ConValue::Char(a), ConValue::Char(b)) => {
ConValue::String([a, b].into_iter().collect::<String>().into()) ConValue::String([a, b].into_iter().collect::<String>().into())
@ -219,18 +224,21 @@ ops! {
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.checked_div(b).unwrap_or_else(|| { (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.checked_div(b).unwrap_or_else(|| {
eprintln!("Warning: Divide by zero in {a} / {b}"); a eprintln!("Warning: Divide by zero in {a} / {b}"); a
})), })),
(ConValue::Float(a), ConValue::Float(b)) => ConValue::Float(a / b),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
Mul: mul = [ Mul: mul = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_mul(b)), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_mul(b)),
(ConValue::Float(a), ConValue::Float(b)) => ConValue::Float(a * b),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
Rem: rem = [ Rem: rem = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.checked_rem(b).unwrap_or_else(|| { (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.checked_rem(b).unwrap_or_else(|| {
eprintln!("Warning: Divide by zero in {a} % {b}"); a println!("Warning: Divide by zero in {a} % {b}"); a
})), })),
(ConValue::Float(a), ConValue::Float(b)) => ConValue::Float(a % b),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
Shl: shl = [ Shl: shl = [
@ -246,6 +254,7 @@ ops! {
Sub: sub = [ Sub: sub = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_sub(b)), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_sub(b)),
(ConValue::Float(a), ConValue::Float(b)) => ConValue::Float(a - b),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
} }
@ -254,6 +263,7 @@ impl std::fmt::Display for ConValue {
match self { match self {
ConValue::Empty => "Empty".fmt(f), ConValue::Empty => "Empty".fmt(f),
ConValue::Int(v) => v.fmt(f), ConValue::Int(v) => v.fmt(f),
ConValue::Float(v) => v.fmt(f),
ConValue::Bool(v) => v.fmt(f), ConValue::Bool(v) => v.fmt(f),
ConValue::Char(v) => v.fmt(f), ConValue::Char(v) => v.fmt(f),
ConValue::String(v) => v.fmt(f), ConValue::String(v) => v.fmt(f),

View File

@ -358,6 +358,9 @@ fn cast(value: ConValue, ty: Sym) -> IResult<ConValue> {
ConValue::Bool(b) => b as _, ConValue::Bool(b) => b as _,
ConValue::Char(c) => c as _, ConValue::Char(c) => c as _,
ConValue::Ref(v) => return cast((*v).clone(), ty), ConValue::Ref(v) => return cast((*v).clone(), ty),
// TODO: This, better
ConValue::Float(_) if ty.starts_with('f') => return Ok(value),
ConValue::Float(f) => f as _,
_ => Err(Error::TypeError)?, _ => Err(Error::TypeError)?,
}; };
Ok(match &*ty { Ok(match &*ty {
@ -369,6 +372,8 @@ fn cast(value: ConValue, ty: Sym) -> IResult<ConValue> {
"i32" => ConValue::Int(value as i32 as _), "i32" => ConValue::Int(value as i32 as _),
"u64" => ConValue::Int(value), "u64" => ConValue::Int(value),
"i64" => ConValue::Int(value), "i64" => ConValue::Int(value),
"f32" => ConValue::Float(value as f32 as _),
"f64" => ConValue::Float(value as f64 as _),
"char" => ConValue::Char(char::from_u32(value as _).unwrap_or('\u{fffd}')), "char" => ConValue::Char(char::from_u32(value as _).unwrap_or('\u{fffd}')),
"bool" => ConValue::Bool(value < 0), "bool" => ConValue::Bool(value < 0),
_ => Err(Error::NotDefined(ty))?, _ => Err(Error::NotDefined(ty))?,