Skip to main content

virtual_rust/interpreter/
cast.rs

1//! Type casting (`as` expressions).
2
3use crate::ast::Type;
4use crate::interpreter::error::RuntimeError;
5use crate::interpreter::value::Value;
6
7/// Casts a [`Value`] to the specified target [`Type`].
8///
9/// Follows Rust's `as` casting semantics for numeric types.
10/// Unknown casts are treated as no-ops.
11pub fn type_cast(value: Value, target: &Type) -> Result<Value, RuntimeError> {
12    match (value, target) {
13        // ── Int → Int (narrowing/widening) ───────────────────────────
14        (Value::Int(n), Type::I8) => Ok(Value::Int(n as i8 as i64)),
15        (Value::Int(n), Type::I16) => Ok(Value::Int(n as i16 as i64)),
16        (Value::Int(n), Type::I32) => Ok(Value::Int(n as i32 as i64)),
17        (Value::Int(n), Type::I64 | Type::I128) => Ok(Value::Int(n)),
18        (Value::Int(n), Type::U8) => Ok(Value::Int(n as u8 as i64)),
19        (Value::Int(n), Type::U16) => Ok(Value::Int(n as u16 as i64)),
20        (Value::Int(n), Type::U32) => Ok(Value::Int(n as u32 as i64)),
21        (Value::Int(n), Type::U64 | Type::U128) => Ok(Value::Int(n as u64 as i64)),
22        (Value::Int(n), Type::Usize) => Ok(Value::Int(n as usize as i64)),
23        (Value::Int(n), Type::Isize) => Ok(Value::Int(n as isize as i64)),
24
25        // ── Int → Float ──────────────────────────────────────────────
26        (Value::Int(n), Type::F32) => Ok(Value::Float(n as f32 as f64)),
27        (Value::Int(n), Type::F64) => Ok(Value::Float(n as f64)),
28
29        // ── Int → Char ───────────────────────────────────────────────
30        (Value::Int(n), Type::Char) => {
31            Ok(Value::Char(char::from_u32(n as u32).unwrap_or('\0')))
32        }
33
34        // ── Float → Int ──────────────────────────────────────────────
35        (Value::Float(n), Type::I32) => Ok(Value::Int(n as i32 as i64)),
36        (Value::Float(n), Type::I64) => Ok(Value::Int(n as i64)),
37        (Value::Float(n), Type::U32) => Ok(Value::Int(n as u32 as i64)),
38        (Value::Float(n), Type::U64) => Ok(Value::Int(n as u64 as i64)),
39        (Value::Float(n), Type::Usize) => Ok(Value::Int(n as usize as i64)),
40
41        // ── Float → Float ────────────────────────────────────────────
42        (Value::Float(n), Type::F32) => Ok(Value::Float(n as f32 as f64)),
43        (Value::Float(n), Type::F64) => Ok(Value::Float(n)),
44
45        // ── Char → Int ───────────────────────────────────────────────
46        (Value::Char(c), Type::U8) => Ok(Value::Int(c as u8 as i64)),
47        (Value::Char(c), Type::U32) => Ok(Value::Int(c as u32 as i64)),
48        (Value::Char(c), Type::I32) => Ok(Value::Int(c as i32 as i64)),
49
50        // ── Bool → Int ───────────────────────────────────────────────
51        (Value::Bool(b), Type::I32 | Type::U8) => Ok(Value::Int(b as i64)),
52
53        // ── Fallback: no-op ──────────────────────────────────────────
54        (v, _) => Ok(v),
55    }
56}