rust/src/interpreter/cast.rs

104 lines
4.7 KiB
Rust
Raw Normal View History

2016-09-07 18:34:59 +02:00
use super::{
EvalContext,
};
use error::{EvalResult, EvalError};
use rustc::ty;
use primval::PrimVal;
use memory::Pointer;
use rustc::ty::Ty;
use syntax::ast::{self, IntTy, UintTy};
2016-09-07 18:34:59 +02:00
impl<'a, 'tcx> EvalContext<'a, 'tcx> {
pub(super) fn cast_primval(&self, val: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
use primval::PrimVal::*;
match val {
Bool(b) => self.cast_const_int(b as u64, ty, false),
F32(f) => self.cast_const_float(f as f64, ty),
F64(f) => self.cast_const_float(f, ty),
I8(i) => self.cast_signed_int(i as i64, ty),
I16(i) => self.cast_signed_int(i as i64, ty),
I32(i) => self.cast_signed_int(i as i64, ty),
I64(i) => self.cast_signed_int(i, ty),
U8(u) => self.cast_const_int(u as u64, ty, false),
U16(u) => self.cast_const_int(u as u64, ty, false),
U32(u) => self.cast_const_int(u as u64, ty, false),
Char(c) => self.cast_const_int(c as u64, ty, false),
2016-09-22 15:47:16 +02:00
U64(u) => self.cast_const_int(u, ty, false),
2016-09-07 18:34:59 +02:00
FnPtr(ptr) |
2016-09-21 23:23:50 -06:00
Ptr(ptr) => self.cast_ptr(ptr, ty),
2016-09-07 18:34:59 +02:00
}
}
fn cast_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
use primval::PrimVal::*;
match ty.sty {
ty::TyRef(..) |
2016-09-21 23:23:50 -06:00
ty::TyRawPtr(_) => Ok(Ptr(ptr)),
2016-09-07 18:34:59 +02:00
ty::TyFnPtr(_) => Ok(FnPtr(ptr)),
ty::TyInt(IntTy::I8) => Ok(I8(ptr.to_int()? as i8)),
ty::TyInt(IntTy::I16) => Ok(I16(ptr.to_int()? as i16)),
ty::TyInt(IntTy::I32) => Ok(I32(ptr.to_int()? as i32)),
ty::TyInt(IntTy::I64) => Ok(I64(ptr.to_int()? as i64)),
ty::TyUint(UintTy::U8) => Ok(U8(ptr.to_int()? as u8)),
ty::TyUint(UintTy::U16) => Ok(U16(ptr.to_int()? as u16)),
ty::TyUint(UintTy::U32) => Ok(U32(ptr.to_int()? as u32)),
ty::TyUint(UintTy::U64) => Ok(U64(ptr.to_int()? as u64)),
2016-09-07 18:34:59 +02:00
_ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))),
}
}
fn cast_signed_int(&self, val: i64, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
self.cast_const_int(val as u64, ty, val < 0)
}
fn cast_const_int(&self, v: u64, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> {
use primval::PrimVal::*;
match ty.sty {
ty::TyBool if v == 0 => Ok(Bool(false)),
ty::TyBool if v == 1 => Ok(Bool(true)),
ty::TyBool => Err(EvalError::InvalidBool),
ty::TyInt(ast::IntTy::I8) => Ok(I8(v as i64 as i8)),
ty::TyInt(ast::IntTy::I16) => Ok(I16(v as i64 as i16)),
ty::TyInt(ast::IntTy::I32) => Ok(I32(v as i64 as i32)),
ty::TyInt(ast::IntTy::I64) => Ok(I64(v as i64)),
ty::TyInt(ast::IntTy::Is) => {
let int_ty = self.tcx.sess.target.int_type;
let ty = self.tcx.mk_mach_int(int_ty);
self.cast_const_int(v, ty, negative)
},
ty::TyUint(ast::UintTy::U8) => Ok(U8(v as u8)),
ty::TyUint(ast::UintTy::U16) => Ok(U16(v as u16)),
ty::TyUint(ast::UintTy::U32) => Ok(U32(v as u32)),
ty::TyUint(ast::UintTy::U64) => Ok(U64(v)),
ty::TyUint(ast::UintTy::Us) => {
let uint_ty = self.tcx.sess.target.uint_type;
let ty = self.tcx.mk_mach_uint(uint_ty);
self.cast_const_int(v, ty, negative)
},
ty::TyFloat(ast::FloatTy::F64) if negative => Ok(F64(v as i64 as f64)),
ty::TyFloat(ast::FloatTy::F64) => Ok(F64(v as f64)),
ty::TyFloat(ast::FloatTy::F32) if negative => Ok(F32(v as i64 as f32)),
ty::TyFloat(ast::FloatTy::F32) => Ok(F32(v as f32)),
2016-09-22 15:47:16 +02:00
ty::TyRawPtr(_) => Ok(Ptr(Pointer::from_int(v as usize))),
2016-09-07 18:34:59 +02:00
ty::TyChar if v as u8 as u64 == v => Ok(Char(v as u8 as char)),
ty::TyChar => Err(EvalError::InvalidChar(v)),
_ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))),
}
}
fn cast_const_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
use primval::PrimVal::*;
match ty.sty {
// casting negative floats to unsigned integers yields zero
ty::TyUint(_) if val < 0.0 => self.cast_const_int(0, ty, false),
ty::TyInt(_) if val < 0.0 => self.cast_const_int(val as i64 as u64, ty, true),
ty::TyInt(_) | ty::TyUint(_) => self.cast_const_int(val as u64, ty, false),
ty::TyFloat(ast::FloatTy::F64) => Ok(F64(val)),
ty::TyFloat(ast::FloatTy::F32) => Ok(F32(val as f32)),
_ => Err(EvalError::Unimplemented(format!("float to {:?} cast", ty))),
}
}
}