implement char handling

This commit is contained in:
Oliver Schneider 2016-06-20 12:29:45 +02:00
parent 579628f56d
commit 2dbd30fa51
No known key found for this signature in database
GPG Key ID: 56D6EEA0FC67AC46
6 changed files with 42 additions and 1 deletions

View File

@ -28,6 +28,7 @@ pub enum EvalError<'tcx> {
ExecuteMemory,
ArrayIndexOutOfBounds(Span, u64, u64),
Math(Span, ConstMathErr),
InvalidChar(u32),
}
pub type EvalResult<'tcx, T> = Result<T, EvalError<'tcx>>;
@ -66,6 +67,8 @@ impl<'tcx> Error for EvalError<'tcx> {
"array index out of bounds",
EvalError::Math(..) =>
"mathematical operation failed",
EvalError::InvalidChar(..) =>
"tried to interpret an invalid 32-bit value as a char",
}
}
@ -85,6 +88,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
write!(f, "array index {} out of bounds {} at {:?}", index, len, span),
EvalError::Math(span, ref err) =>
write!(f, "mathematical operation at {:?} failed with {:?}", span, err),
EvalError::InvalidChar(c) =>
write!(f, "invalid utf8 character: {}", c),
_ => write!(f, "{}", self.description()),
}
}

View File

@ -208,7 +208,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.memory.write_bool(ptr, b)?;
Ok(ptr)
}
Char(_c) => unimplemented!(),
Char(c) => {
let ptr = self.memory.allocate(4);
self.memory.write_uint(ptr, c as u32 as u64, 4)?;
Ok(ptr)
},
Struct(_node_id) => unimplemented!(),
Tuple(_node_id) => unimplemented!(),
Function(_def_id) => unimplemented!(),
@ -1371,6 +1375,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
use syntax::ast::{IntTy, UintTy};
let val = match (self.memory.pointer_size, &ty.sty) {
(_, &ty::TyBool) => PrimVal::Bool(self.memory.read_bool(ptr)?),
(_, &ty::TyChar) => {
let c = self.memory.read_uint(ptr, 4)? as u32;
match ::std::char::from_u32(c) {
Some(ch) => PrimVal::Char(ch),
None => return Err(EvalError::InvalidChar(c)),
}
}
(_, &ty::TyInt(IntTy::I8)) => PrimVal::I8(self.memory.read_int(ptr, 1)? as i8),
(2, &ty::TyInt(IntTy::Is)) |
(_, &ty::TyInt(IntTy::I16)) => PrimVal::I16(self.memory.read_int(ptr, 2)? as i16),

View File

@ -369,6 +369,7 @@ impl<'tcx> Memory<'tcx> {
PrimVal::U16(n) => self.write_uint(ptr, n as u64, 2),
PrimVal::U32(n) => self.write_uint(ptr, n as u64, 4),
PrimVal::U64(n) => self.write_uint(ptr, n as u64, 8),
PrimVal::Char(c) => self.write_uint(ptr, c as u32 as u64, 4),
PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size),
PrimVal::FnPtr(_p) |
PrimVal::AbstractPtr(_p) => unimplemented!(),

View File

@ -12,6 +12,7 @@ pub enum PrimVal {
AbstractPtr(Pointer),
FnPtr(Pointer),
IntegerPtr(u64),
Char(char),
}
/// returns the result of the operation and whether the operation overflowed
@ -127,6 +128,15 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
(U16(l), U16(r)) => int_binops!(U16, l, r),
(U32(l), U32(r)) => int_binops!(U32, l, r),
(U64(l), U64(r)) => int_binops!(U64, l, r),
(Char(l), Char(r)) => match bin_op {
Eq => Bool(l == r),
Ne => Bool(l != r),
Lt => Bool(l < r),
Le => Bool(l <= r),
Gt => Bool(l > r),
Ge => Bool(l >= r),
_ => panic!("invalid char op: {:?}", bin_op),
},
(Bool(l), Bool(r)) => {
Bool(match bin_op {

View File

@ -0,0 +1,5 @@
//error-pattern: can't handle cast: tmp0 as isize (Misc)
// no-ignore-x86 ignore-x86_64
fn main() {
assert_eq!(std::char::from_u32('x' as u32), Some('x'));
}

9
tests/run-pass/char.rs Normal file
View File

@ -0,0 +1,9 @@
fn main() {
let c = 'x';
assert_eq!(c, 'x');
assert!('a' < 'z');
assert!('1' < '9');
assert_eq!(std::char::from_u32('x' as u32).unwrap(), 'x');
// FIXME:
// assert_eq!(std::char::from_u32('x' as u32), Some('x'));
}