auto merge of #8974 : thestinger/rust/char, r=huonw

Closes #7609
This commit is contained in:
bors 2013-09-04 05:10:55 -07:00
commit 51331f61f3
45 changed files with 227 additions and 215 deletions

View File

@ -158,6 +158,7 @@ def emit_property_module(f, mod, tbl):
keys.sort()
emit_bsearch_range_table(f);
for cat in keys:
if cat == "Cs": continue
f.write(" static %s_table : &'static [(char,char)] = &[\n" % cat)
ix = 0
for pair in tbl[cat]:

View File

@ -10,7 +10,6 @@
#[allow(missing_doc)];
use std::str;
// Simple Extensible Binary Markup Language (ebml) reader and writer on a
@ -90,6 +89,7 @@ pub enum EbmlEncoderTag {
// --------------------------------------
pub mod reader {
use std::char;
use super::*;
use serialize;
@ -426,7 +426,7 @@ pub mod reader {
(unsafe { transmute::<u64, f64>(bits) }) as float
}
fn read_char(&mut self) -> char {
doc_as_u32(self.next_doc(EsChar)) as char
char::from_u32(doc_as_u32(self.next_doc(EsChar))).unwrap()
}
fn read_str(&mut self) -> ~str {
self.next_doc(EsStr).as_str()

View File

@ -16,6 +16,8 @@
//! json parsing and serialization
use std::char;
use std::cast::transmute;
use std::iterator;
use std::float;
use std::hashmap::HashMap;
@ -490,7 +492,7 @@ pub struct Parser<T> {
pub fn Parser<T : iterator::Iterator<char>>(rdr: ~T) -> Parser<T> {
let mut p = Parser {
rdr: rdr,
ch: 0 as char,
ch: '\x00',
line: 1,
col: 0,
};
@ -517,12 +519,13 @@ impl<T: iterator::Iterator<char>> Parser<T> {
}
impl<T : iterator::Iterator<char>> Parser<T> {
fn eof(&self) -> bool { self.ch == -1 as char }
// FIXME: #8971: unsound
fn eof(&self) -> bool { self.ch == unsafe { transmute(-1u32) } }
fn bump(&mut self) {
match self.rdr.next() {
Some(ch) => self.ch = ch,
None() => self.ch = -1 as char,
None() => self.ch = unsafe { transmute(-1u32) }, // FIXME: #8971: unsound
}
if self.ch == '\n' {
@ -755,7 +758,7 @@ impl<T : iterator::Iterator<char>> Parser<T> {
~"invalid \\u escape (not four digits)");
}
res.push_char(n as char);
res.push_char(char::from_u32(n as u32).unwrap());
}
_ => return self.error(~"invalid escape")
}

View File

@ -258,7 +258,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
' ' => flags.space = true,
'.' => fstate = FormatStatePrecision,
'0'..'9' => {
flags.width = (cur - '0') as uint;
flags.width = (cur as uint - '0' as uint);
fstate = FormatStateWidth;
}
_ => util::unreachable()
@ -330,7 +330,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
state = Nothing;
}
'0'..'9' => {
state = IntConstant(i*10 + ((cur - '0') as int));
state = IntConstant(i*10 + (cur as int - '0' as int));
old_state = Nothing;
}
_ => return Err(~"bad int constant")
@ -358,7 +358,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
flags.space = true;
}
(FormatStateFlags,'0'..'9') => {
flags.width = (cur - '0') as uint;
flags.width = (cur as uint - '0' as uint);
*fstate = FormatStateWidth;
}
(FormatStateFlags,'.') => {
@ -366,7 +366,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
}
(FormatStateWidth,'0'..'9') => {
let old = flags.width;
flags.width = flags.width * 10 + ((cur - '0') as uint);
flags.width = flags.width * 10 + (cur as uint - '0' as uint);
if flags.width < old { return Err(~"format width overflow") }
}
(FormatStateWidth,'.') => {
@ -374,7 +374,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
}
(FormatStatePrecision,'0'..'9') => {
let old = flags.precision;
flags.precision = flags.precision * 10 + ((cur - '0') as uint);
flags.precision = flags.precision * 10 + (cur as uint - '0' as uint);
if flags.precision < old { return Err(~"format precision overflow") }
}
_ => return Err(~"invalid format specifier")

View File

@ -72,7 +72,7 @@ fn encode_inner(s: &str, full_url: bool) -> ~str {
let mut out = ~"";
while !rdr.eof() {
let ch = rdr.read_byte() as char;
let ch = rdr.read_byte() as u8 as char;
match ch {
// unreserved:
'A' .. 'Z' |
@ -135,7 +135,7 @@ fn decode_inner(s: &str, full_url: bool) -> ~str {
match rdr.read_char() {
'%' => {
let bytes = rdr.read_bytes(2u);
let ch = uint::parse_bytes(bytes, 16u).unwrap() as char;
let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8 as char;
if full_url {
// Only decode some characters:
@ -186,7 +186,7 @@ fn encode_plus(s: &str) -> ~str {
let mut out = ~"";
while !rdr.eof() {
let ch = rdr.read_byte() as char;
let ch = rdr.read_byte() as u8 as char;
match ch {
'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => {
out.push_char(ch);
@ -258,7 +258,7 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
let ch = match ch {
'%' => {
let bytes = rdr.read_bytes(2u);
uint::parse_bytes(bytes, 16u).unwrap() as char
uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
}
'+' => ' ',
ch => ch
@ -295,7 +295,7 @@ fn split_char_first(s: &str, c: char) -> (~str, ~str) {
do io::with_str_reader(s) |rdr| {
let mut ch;
while !rdr.eof() {
ch = rdr.read_byte() as char;
ch = rdr.read_byte() as u8 as char;
if ch == c {
// found a match, adjust markers
index = rdr.tell()-1;

View File

@ -239,10 +239,10 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, st: &ty::sty) {
ty::ty_nil => w.write_char('n'),
ty::ty_bot => w.write_char('z'),
ty::ty_bool => w.write_char('b'),
ty::ty_char => w.write_char('c'),
ty::ty_int(t) => {
match t {
ty_i => w.write_char('i'),
ty_char => w.write_char('c'),
ty_i8 => w.write_str(&"MB"),
ty_i16 => w.write_str(&"MW"),
ty_i32 => w.write_str(&"ML"),

View File

@ -200,21 +200,19 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
}
}
match e.node {
ExprLit(@codemap::Spanned {node: lit_int(v, t), _}) => {
if t != ty_char {
ExprLit(@codemap::Spanned {node: lit_int(v, t), _}) => {
if (v as u64) > ast_util::int_ty_max(
if t == ty_i { sess.targ_cfg.int_type } else { t }) {
sess.span_err(e.span, "literal out of range for its type");
}
}
}
ExprLit(@codemap::Spanned {node: lit_uint(v, t), _}) => {
if v > ast_util::uint_ty_max(
if t == ty_u { sess.targ_cfg.uint_type } else { t }) {
sess.span_err(e.span, "literal out of range for its type");
ExprLit(@codemap::Spanned {node: lit_uint(v, t), _}) => {
if v > ast_util::uint_ty_max(
if t == ty_u { sess.targ_cfg.uint_type } else { t }) {
sess.span_err(e.span, "literal out of range for its type");
}
}
}
_ => ()
_ => ()
}
visit::walk_expr(v, e, is_const);
}

View File

@ -472,6 +472,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
pub fn lit_to_const(lit: &lit) -> const_val {
match lit.node {
lit_str(s) => const_str(s),
lit_char(n) => const_uint(n as u64),
lit_int(n, _) => const_int(n),
lit_uint(n, _) => const_uint(n),
lit_int_unsuffixed(n) => const_int(n),

View File

@ -778,7 +778,6 @@ impl TypeLimitsLintVisitor {
fn int_ty_range(&mut self, int_ty: ast::int_ty) -> (i64, i64) {
match int_ty {
ast::ty_i => (i64::min_value, i64::max_value),
ast::ty_char => (u32::min_value as i64, u32::max_value as i64),
ast::ty_i8 => (i8::min_value as i64, i8::max_value as i64),
ast::ty_i16 => (i16::min_value as i64, i16::max_value as i64),
ast::ty_i32 => (i32::min_value as i64, i32::max_value as i64),

View File

@ -777,7 +777,7 @@ pub fn PrimitiveTypeTable() -> PrimitiveTypeTable {
};
table.intern("bool", ty_bool);
table.intern("char", ty_int(ty_char));
table.intern("char", ty_char);
table.intern("float", ty_float(ty_f));
table.intern("f32", ty_float(ty_f32));
table.intern("f64", ty_float(ty_f64));

View File

@ -566,6 +566,7 @@ pub fn compare_scalar_types(cx: @mut Block,
match ty::get(t).sty {
ty::ty_nil => rslt(cx, f(nil_type)),
ty::ty_bool | ty::ty_ptr(_) => rslt(cx, f(unsigned_int)),
ty::ty_char => rslt(cx, f(unsigned_int)),
ty::ty_int(_) => rslt(cx, f(signed_int)),
ty::ty_uint(_) => rslt(cx, f(unsigned_int)),
ty::ty_float(_) => rslt(cx, f(floating_point)),

View File

@ -39,6 +39,7 @@ pub fn const_lit(cx: &mut CrateContext, e: &ast::Expr, lit: ast::lit)
-> ValueRef {
let _icx = push_ctxt("trans_lit");
match lit.node {
ast::lit_char(i) => C_integral(Type::char(), i as u64, false),
ast::lit_int(i, t) => C_integral(Type::int_from_ty(cx, t), i as u64, true),
ast::lit_uint(u, t) => C_integral(Type::uint_from_ty(cx, t), u, false),
ast::lit_int_unsuffixed(i) => {

View File

@ -746,9 +746,9 @@ fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
let (name, encoding) = match ty::get(t).sty {
ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned),
ty::ty_bool => (~"bool", DW_ATE_boolean),
ty::ty_char => (~"char", DW_ATE_unsigned_char),
ty::ty_int(int_ty) => match int_ty {
ast::ty_i => (~"int", DW_ATE_signed),
ast::ty_char => (~"char", DW_ATE_signed_char),
ast::ty_i8 => (~"i8", DW_ATE_signed),
ast::ty_i16 => (~"i16", DW_ATE_signed),
ast::ty_i32 => (~"i32", DW_ATE_signed),
@ -1344,6 +1344,7 @@ fn type_metadata(cx: &mut CrateContext,
ty::ty_nil |
ty::ty_bot |
ty::ty_bool |
ty::ty_char |
ty::ty_int(_) |
ty::ty_uint(_) |
ty::ty_float(_) => {

View File

@ -1630,6 +1630,7 @@ pub enum cast_kind {
pub fn cast_type_kind(t: ty::t) -> cast_kind {
match ty::get(t).sty {
ty::ty_char => cast_integral,
ty::ty_float(*) => cast_float,
ty::ty_ptr(*) => cast_pointer,
ty::ty_rptr(*) => cast_pointer,

View File

@ -157,8 +157,8 @@ impl Reflector {
ty::ty_bot => self.leaf("bot"),
ty::ty_nil => self.leaf("nil"),
ty::ty_bool => self.leaf("bool"),
ty::ty_char => self.leaf("char"),
ty::ty_int(ast::ty_i) => self.leaf("int"),
ty::ty_int(ast::ty_char) => self.leaf("char"),
ty::ty_int(ast::ty_i8) => self.leaf("i8"),
ty::ty_int(ast::ty_i16) => self.leaf("i16"),
ty::ty_int(ast::ty_i32) => self.leaf("i32"),

View File

@ -119,7 +119,6 @@ impl Type {
pub fn int_from_ty(ctx: &CrateContext, t: ast::int_ty) -> Type {
match t {
ast::ty_i => ctx.int_type,
ast::ty_char => Type::char(),
ast::ty_i8 => Type::i8(),
ast::ty_i16 => Type::i16(),
ast::ty_i32 => Type::i32(),

View File

@ -108,6 +108,7 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type {
let llsizingty = match ty::get(t).sty {
ty::ty_nil | ty::ty_bot => Type::nil(),
ty::ty_bool => Type::bool(),
ty::ty_char => Type::char(),
ty::ty_int(t) => Type::int_from_ty(cx, t),
ty::ty_uint(t) => Type::uint_from_ty(cx, t),
ty::ty_float(t) => Type::float_from_ty(cx, t),
@ -195,6 +196,7 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
let mut llty = match ty::get(t).sty {
ty::ty_nil | ty::ty_bot => Type::nil(),
ty::ty_bool => Type::bool(),
ty::ty_char => Type::char(),
ty::ty_int(t) => Type::int_from_ty(cx, t),
ty::ty_uint(t) => Type::uint_from_ty(cx, t),
ty::ty_float(t) => Type::float_from_ty(cx, t),

View File

@ -572,8 +572,8 @@ mod primitives {
def_prim_ty!(TY_NIL, super::ty_nil, 0)
def_prim_ty!(TY_BOOL, super::ty_bool, 1)
def_prim_ty!(TY_INT, super::ty_int(ast::ty_i), 2)
def_prim_ty!(TY_CHAR, super::ty_int(ast::ty_char), 3)
def_prim_ty!(TY_CHAR, super::ty_char, 2)
def_prim_ty!(TY_INT, super::ty_int(ast::ty_i), 3)
def_prim_ty!(TY_I8, super::ty_int(ast::ty_i8), 4)
def_prim_ty!(TY_I16, super::ty_int(ast::ty_i16), 5)
def_prim_ty!(TY_I32, super::ty_int(ast::ty_i32), 6)
@ -609,6 +609,7 @@ pub enum sty {
ty_nil,
ty_bot,
ty_bool,
ty_char,
ty_int(ast::int_ty),
ty_uint(ast::uint_ty),
ty_float(ast::float_ty),
@ -1016,7 +1017,7 @@ fn mk_t(cx: ctxt, st: sty) -> t {
flags |= rflags(r);
flags |= get(mt.ty).flags;
}
&ty_nil | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
&ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
&ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
&ty_opaque_box => (),
// You might think that we could just return ty_err for
@ -1147,7 +1148,6 @@ pub fn mk_u64() -> t { mk_prim_t(&primitives::TY_U64) }
pub fn mk_mach_int(tm: ast::int_ty) -> t {
match tm {
ast::ty_i => mk_int(),
ast::ty_char => mk_char(),
ast::ty_i8 => mk_i8(),
ast::ty_i16 => mk_i16(),
ast::ty_i32 => mk_i32(),
@ -1303,7 +1303,7 @@ pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
return;
}
match get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
}
@ -1400,7 +1400,7 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
ty_struct(did, ref substs) => {
ty_struct(did, fold_substs(substs, fldop))
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self(_) => {
(*sty).clone()
@ -1745,7 +1745,7 @@ pub fn type_is_unique(ty: t) -> bool {
*/
pub fn type_is_scalar(ty: t) -> bool {
match get(ty).sty {
ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_nil | ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
ty_bare_fn(*) | ty_ptr(_) => true,
_ => false
@ -2079,7 +2079,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
let result = match get(ty).sty {
// Scalar and unique types are sendable, freezable, and durable
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_bare_fn(_) | ty_ptr(_) => {
TC_NONE
}
@ -2414,6 +2414,7 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
ty_nil |
ty_bot |
ty_bool |
ty_char |
ty_int(_) |
ty_uint(_) |
ty_float(_) |
@ -2551,7 +2552,7 @@ pub fn type_is_integral(ty: t) -> bool {
pub fn type_is_char(ty: t) -> bool {
match get(ty).sty {
ty_int(ty_char) => true,
ty_char => true,
_ => false
}
}
@ -2588,7 +2589,7 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
let mut result = true;
match get(ty).sty {
// Scalar types
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
// Boxed types
ty_box(_) | ty_uniq(_) | ty_closure(_) |
@ -3428,7 +3429,7 @@ pub fn occurs_check(tcx: ctxt, sp: Span, vid: TyVid, rt: t) {
pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
match get(t).sty {
ty_nil | ty_bot | ty_bool | ty_int(_) |
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
ty_uint(_) | ty_float(_) | ty_estr(_) |
ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
::util::ppaux::ty_to_str(cx, t)
@ -4262,10 +4263,11 @@ pub fn struct_fields(cx: ctxt, did: ast::DefId, substs: &substs)
pub fn is_binopable(cx: ctxt, ty: t, op: ast::BinOp) -> bool {
static tycat_other: int = 0;
static tycat_bool: int = 1;
static tycat_int: int = 2;
static tycat_float: int = 3;
static tycat_struct: int = 4;
static tycat_bot: int = 5;
static tycat_char: int = 2;
static tycat_int: int = 3;
static tycat_float: int = 4;
static tycat_struct: int = 5;
static tycat_bot: int = 6;
static opcat_add: int = 0;
static opcat_sub: int = 1;
@ -4304,6 +4306,7 @@ pub fn is_binopable(cx: ctxt, ty: t, op: ast::BinOp) -> bool {
return tycat(cx, simd_type(cx, ty))
}
match get(ty).sty {
ty_char => tycat_char,
ty_bool => tycat_bool,
ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
@ -4316,16 +4319,15 @@ pub fn is_binopable(cx: ctxt, ty: t, op: ast::BinOp) -> bool {
static t: bool = true;
static f: bool = false;
let tbl = ~[
/*. add, shift, bit
. sub, rel, logic
. mult, eq, */
/*other*/ ~[f, f, f, f, f, f, f, f],
/*bool*/ ~[f, f, f, f, t, t, t, t],
/*int*/ ~[t, t, t, t, t, t, t, f],
/*float*/ ~[t, t, t, f, t, t, f, f],
/*bot*/ ~[f, f, f, f, f, f, f, f],
/*struct*/ ~[t, t, t, t, f, f, t, t]];
let tbl = [
// +, -, *, shift, rel, ==, bit, logic
/*other*/ [f, f, f, f, f, f, f, f],
/*bool*/ [f, f, f, f, t, t, t, t],
/*char*/ [f, f, f, f, t, t, f, f],
/*int*/ [t, t, t, t, t, t, t, f],
/*float*/ [t, t, t, f, t, t, f, f],
/*bot*/ [f, f, f, f, f, f, f, f],
/*struct*/ [t, t, t, t, f, f, t, t]];
return tbl[tycat(cx, ty)][opcat(op)];
}

View File

@ -455,6 +455,10 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope + Clone + 'static>(
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
ty::mk_bool()
}
ast::ty_char => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
ty::mk_char()
}
ast::ty_int(it) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
ty::mk_mach_int(it)

View File

@ -434,7 +434,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::Pat, expected: ty::t) {
|| ~"mismatched types in range")
{
// no-op
} else if !ty::type_is_numeric(b_ty) {
} else if !ty::type_is_numeric(b_ty) && !ty::type_is_char(b_ty) {
tcx.sess.span_err(pat.span, "non-numeric type used in range");
} else {
match valid_range_bounds(fcx.ccx, begin, end) {

View File

@ -783,7 +783,7 @@ impl<'self> LookupContext<'self> {
ty_infer(IntVar(_)) |
ty_infer(FloatVar(_)) |
ty_self(_) | ty_param(*) | ty_nil | ty_bot | ty_bool |
ty_int(*) | ty_uint(*) |
ty_char | ty_int(*) | ty_uint(*) |
ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_struct(*) | ty_tup(*) |
ty_estr(*) | ty_evec(*) | ty_trait(*) | ty_closure(*) => {
self.search_for_some_kind_of_autorefd_method(

View File

@ -1021,6 +1021,7 @@ pub fn check_lit(fcx: @mut FnCtxt, lit: @ast::lit) -> ty::t {
match lit.node {
ast::lit_str(*) => ty::mk_estr(tcx, ty::vstore_slice(ty::re_static)),
ast::lit_char(_) => ty::mk_char(),
ast::lit_int(_, t) => ty::mk_mach_int(t),
ast::lit_uint(_, t) => ty::mk_mach_uint(t),
ast::lit_int_unsuffixed(_) => {
@ -2695,10 +2696,20 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}, t_e, None);
}
let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
if type_is_c_like_enum(fcx,expr.span,t_e)
&& t_1_is_scalar {
/* this case is allowed */
let te = structurally_resolved_type(fcx, e.span, t_e);
let t_1_is_char = type_is_char(fcx, expr.span, t_1);
// casts to scalars other than `char` are allowed
let t_1_is_trivial = type_is_scalar(fcx, expr.span, t_1) && !t_1_is_char;
if type_is_c_like_enum(fcx, expr.span, t_e) && t_1_is_trivial {
// casts from C-like enums are allowed
} else if t_1_is_char {
if ty::get(te).sty != ty::ty_uint(ast::ty_u8) {
fcx.type_error_message(expr.span, |actual| {
fmt!("only `u8` can be cast as `char`, not `%s`", actual)
}, t_e, None);
}
} else if type_is_region_ptr(fcx, expr.span, t_e) &&
type_is_unsafe_ptr(fcx, expr.span, t_1) {
@ -2729,7 +2740,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
/* this cast is only allowed from &[T] to *T or
&T to *T. */
let te = structurally_resolved_type(fcx, e.span, t_e);
match (&ty::get(te).sty, &ty::get(t_1).sty) {
(&ty::ty_rptr(_, mt1), &ty::ty_ptr(mt2))
if types_compatible(fcx, e.span,
@ -2741,7 +2751,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
}
} else if !(type_is_scalar(fcx,expr.span,t_e)
&& t_1_is_scalar) {
&& t_1_is_trivial) {
/*
If more type combinations should be supported than are
supported here, then file an enhancement issue and
@ -3439,6 +3449,11 @@ pub fn type_is_scalar(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool {
return ty::type_is_scalar(typ_s);
}
pub fn type_is_char(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_char(typ_s);
}
pub fn type_is_unsafe_ptr(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_unsafe_ptr(typ_s);

View File

@ -20,7 +20,7 @@ use metadata::csearch;
use metadata::cstore::iter_crate_data;
use middle::ty::get;
use middle::ty::{ImplContainer, lookup_item_type, subst};
use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err};
use middle::ty::{substs, t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
use middle::ty::{ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
@ -81,7 +81,7 @@ pub fn get_base_type(inference_context: @mut InferCtxt,
Some(resolved_type)
}
ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) |
ty_nil | ty_bot | ty_bool | ty_char | ty_int(*) | ty_uint(*) | ty_float(*) |
ty_estr(*) | ty_evec(*) | ty_bare_fn(*) | ty_closure(*) | ty_tup(*) |
ty_infer(*) | ty_param(*) | ty_self(*) | ty_type | ty_opaque_box |
ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) | ty_err | ty_box(_) |

View File

@ -610,14 +610,10 @@ pub fn super_tys<C:Combine>(
vid: ty::IntVid,
val: ty::IntVarValue) -> cres<ty::t>
{
if val == IntType(ast::ty_char) {
Err(ty::terr_integer_as_char)
} else {
if_ok!(this.infcx().simple_var_t(vid_is_expected, vid, val));
match val {
IntType(v) => Ok(ty::mk_mach_int(v)),
UintType(v) => Ok(ty::mk_mach_uint(v))
}
if_ok!(this.infcx().simple_var_t(vid_is_expected, vid, val));
match val {
IntType(v) => Ok(ty::mk_mach_int(v)),
UintType(v) => Ok(ty::mk_mach_uint(v))
}
}

View File

@ -16,7 +16,7 @@ use middle::ty::{br_fresh, ctxt, field};
use middle::ty::{mt, t, param_ty};
use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region,
re_empty};
use middle::ty::{ty_bool, ty_bot, ty_box, ty_struct, ty_enum};
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure};
use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
use middle::ty::{ty_ptr, ty_rptr, ty_self, ty_tup, ty_type, ty_uniq};
@ -412,8 +412,8 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
ty_nil => ~"()",
ty_bot => ~"!",
ty_bool => ~"bool",
ty_char => ~"char",
ty_int(ast::ty_i) => ~"int",
ty_int(ast::ty_char) => ~"char",
ty_int(t) => ast_util::int_ty_to_str(t),
ty_uint(ast::ty_u) => ~"uint",
ty_uint(t) => ast_util::uint_ty_to_str(t),

View File

@ -10,8 +10,9 @@
//! Utilities for manipulating the char type
use cast::transmute;
use option::{None, Option, Some};
use int;
use i32;
use str::StrSlice;
use unicode::{derived_property, general_category, decompose};
use to_str::ToStr;
@ -64,6 +65,19 @@ static TAG_FOUR_B: uint = 240u;
Cn Unassigned a reserved unassigned code point or a noncharacter
*/
/// The highest valid code point
pub static MAX: char = '\U0010ffff';
/// Convert from `u32` to a character.
pub fn from_u32(i: u32) -> Option<char> {
// catch out-of-bounds and surrogates
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
None
} else {
Some(unsafe { transmute(i) })
}
}
/// Returns whether the specified character is considered a unicode alphabetic
/// character
pub fn is_alphabetic(c: char) -> bool { derived_property::Alphabetic(c) }
@ -194,10 +208,12 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
fail!("from_digit: radix %? is to high (maximum 36)", num);
}
if num < radix {
if num < 10 {
Some(('0' as uint + num) as char)
} else {
Some(('a' as uint + num - 10u) as char)
unsafe {
if num < 10 {
Some(transmute(('0' as uint + num) as u32))
} else {
Some(transmute(('a' as uint + num - 10u) as u32))
}
}
} else {
None
@ -220,14 +236,16 @@ fn decompose_hangul(s: char, f: &fn(char)) {
let si = s as uint - S_BASE;
let li = si / N_COUNT;
f((L_BASE + li) as char);
unsafe {
f(transmute((L_BASE + li) as u32));
let vi = (si % N_COUNT) / T_COUNT;
f((V_BASE + vi) as char);
let vi = (si % N_COUNT) / T_COUNT;
f(transmute((V_BASE + vi) as u32));
let ti = si % T_COUNT;
if ti > 0 {
f((T_BASE + ti) as char);
let ti = si % T_COUNT;
if ti > 0 {
f(transmute((T_BASE + ti) as u32));
}
}
}
@ -267,10 +285,12 @@ pub fn escape_unicode(c: char, f: &fn(char)) {
(c <= '\uffff') { f('u'); 4 }
_ { f('U'); 8 }
);
do int::range_step(4 * (pad - 1), -1, -4) |offset| {
match ((c as u32) >> offset) & 0xf {
i @ 0 .. 9 => { f('0' + i as char); }
i => { f('a' + (i - 10) as char); }
do i32::range_step(4 * (pad - 1), -1, -4) |offset| {
unsafe {
match ((c as i32) >> offset) & 0xf {
i @ 0 .. 9 => { f(transmute('0' as i32 + i)); }
i => { f(transmute('a' as i32 + (i - 10))); }
}
}
true
};
@ -416,8 +436,8 @@ impl Ord for char {
#[cfg(not(test))]
impl Zero for char {
fn zero() -> char { 0 as char }
fn is_zero(&self) -> bool { *self == 0 as char }
fn zero() -> char { '\x00' }
fn is_zero(&self) -> bool { *self == '\x00' }
}
#[test]

View File

@ -47,6 +47,7 @@ implement `Reader` and `Writer`, where appropriate.
#[allow(missing_doc)];
use cast;
use cast::transmute;
use clone::Clone;
use c_str::ToCStr;
use container::Container;
@ -661,7 +662,9 @@ impl<T:Reader> ReaderUtil for T {
i += 1;
assert!((w > 0));
if w == 1 {
chars.push(b0 as char);
unsafe {
chars.push(transmute(b0 as u32));
}
loop;
}
// can't satisfy this char with the existing data
@ -680,7 +683,9 @@ impl<T:Reader> ReaderUtil for T {
// See str::StrSlice::char_at
val += ((b0 << ((w + 1) as u8)) as uint)
<< (w - 1) * 6 - w - 1u;
chars.push(val as char);
unsafe {
chars.push(transmute(val as u32));
}
}
return (i, 0);
}
@ -712,7 +717,7 @@ impl<T:Reader> ReaderUtil for T {
fn read_char(&self) -> char {
let c = self.read_chars(1);
if c.len() == 0 {
return -1 as char; // FIXME will this stay valid? // #2004
return unsafe { transmute(-1u32) }; // FIXME: #8971: unsound
}
assert_eq!(c.len(), 1);
return c[0];
@ -739,9 +744,11 @@ impl<T:Reader> ReaderUtil for T {
}
fn each_char(&self, it: &fn(char) -> bool) -> bool {
// FIXME: #8971: unsound
let eof: char = unsafe { transmute(-1u32) };
loop {
match self.read_char() {
eof if eof == (-1 as char) => break,
c if c == eof => break,
ch => if !it(ch) { return false; }
}
}
@ -1896,6 +1903,7 @@ mod tests {
use result::{Ok, Err};
use u64;
use vec;
use cast::transmute;
#[test]
fn test_simple() {
@ -2002,7 +2010,7 @@ mod tests {
#[test]
fn test_readchar() {
do io::with_str_reader("") |inp| {
let res : char = inp.read_char();
let res = inp.read_char();
assert_eq!(res as int, 29983);
}
}
@ -2010,8 +2018,8 @@ mod tests {
#[test]
fn test_readchar_empty() {
do io::with_str_reader("") |inp| {
let res : char = inp.read_char();
assert_eq!(res as int, -1);
let res = inp.read_char();
assert_eq!(res, unsafe { transmute(-1u32) }); // FIXME: #8971: unsound
}
}

View File

@ -174,13 +174,6 @@ impl Rand for f64 {
}
}
impl Rand for char {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> char {
rng.next() as char
}
}
impl Rand for bool {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> bool {
@ -1137,7 +1130,7 @@ mod test {
let _f : f32 = random();
let _o : Option<Option<i8>> = random();
let _many : ((),
(~uint, @int, ~Option<~(@char, ~(@bool,))>),
(~uint, @int, ~Option<~(@u32, ~(@bool,))>),
(u8, i8, u16, i16, u32, i32, u64, i64),
(f32, (f64, (float,)))) = random();
}

View File

@ -163,13 +163,14 @@ impl<'self> Parser<'self> {
// Read digit
fn read_digit(&mut self, radix: u8) -> Option<u8> {
fn parse_digit(c: char, radix: u8) -> Option<u8> {
let c = c as u8;
// assuming radix is either 10 or 16
if c >= '0' && c <= '9' {
Some((c - '0') as u8)
} else if radix > 10 && c >= 'a' && c < 'a' + (radix - 10) as char {
Some((c - 'a' + (10 as char)) as u8)
} else if radix > 10 && c >= 'A' && c < 'A' + (radix - 10) as char {
Some((c - 'A' + (10 as char)) as u8)
if c >= '0' as u8 && c <= '9' as u8 {
Some((c - '0' as u8) as u8)
} else if radix > 10 && c >= 'a' as u8 && c < 'a' as u8 + (radix - 10) {
Some((c - 'a' as u8 + 10) as u8)
} else if radix > 10 && c >= 'A' as u8 && c < 'A' as u8 + (radix - 10) {
Some((c - 'A' as u8 + 10) as u8)
} else {
None
}

View File

@ -17,6 +17,7 @@
use at_vec;
use cast;
use cast::transmute;
use char;
use char::Char;
use clone::{Clone, DeepClone};
@ -875,18 +876,18 @@ pub fn utf16_chars(v: &[u16], f: &fn(char)) {
let u = v[i];
if u <= 0xD7FF_u16 || u >= 0xE000_u16 {
f(u as char);
f(unsafe { cast::transmute(u as u32) });
i += 1u;
} else {
let u2 = v[i+1u];
assert!(u >= 0xD800_u16 && u <= 0xDBFF_u16);
assert!(u2 >= 0xDC00_u16 && u2 <= 0xDFFF_u16);
let mut c = (u - 0xD800_u16) as char;
let mut c: u32 = (u - 0xD800_u16) as u32;
c = c << 10;
c |= (u2 - 0xDC00_u16) as char;
c |= 0x1_0000_u32 as char;
f(c);
c |= (u2 - 0xDC00_u16) as u32;
c |= 0x1_0000_u32 as u32;
f(unsafe { cast::transmute(c) });
i += 2u;
}
}
@ -953,7 +954,6 @@ macro_rules! utf8_acc_cont_byte(
)
static TAG_CONT_U8: u8 = 128u8;
static MAX_UNICODE: uint = 1114112u;
/// Unsafe operations
pub mod raw {
@ -1942,7 +1942,7 @@ impl<'self> StrSlice<'self> for &'self str {
if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); }
if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); }
return CharRange {ch: val as char, next: i + w};
return CharRange {ch: unsafe { transmute(val as u32) }, next: i + w};
}
return multibyte_char_range_at(*self, i);
@ -1980,7 +1980,7 @@ impl<'self> StrSlice<'self> for &'self str {
if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); }
if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); }
return CharRange {ch: val as char, next: i};
return CharRange {ch: unsafe { transmute(val as u32) }, next: i};
}
return multibyte_char_range_at_rev(*self, prev);
@ -2236,7 +2236,6 @@ impl OwnedStr for ~str {
/// Appends a character to the back of a string
#[inline]
fn push_char(&mut self, c: char) {
assert!((c as uint) < MAX_UNICODE); // FIXME: #7609: should be enforced on all `char`
let cur_len = self.len();
self.reserve_at_least(cur_len + 4); // may use up to 4 bytes
@ -2433,8 +2432,6 @@ impl Default for @str {
mod tests {
use container::Container;
use option::{None, Some};
use libc::c_char;
use libc;
use ptr;
use str::*;
use vec;
@ -3178,13 +3175,6 @@ mod tests {
assert!(!"".contains_char('a'));
}
#[test]
fn test_map() {
#[fixed_stack_segment]; #[inline(never)];
assert_eq!(~"", "".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char));
assert_eq!(~"YMCA", "ymca".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char));
}
#[test]
fn test_utf16() {
let pairs =
@ -3903,26 +3893,6 @@ mod bench {
}
}
#[bench]
fn map_chars_100_ascii(bh: &mut BenchHarness) {
let s = "HelloHelloHelloHelloHelloHelloHelloHelloHelloHello\
HelloHelloHelloHelloHelloHelloHelloHelloHelloHello";
do bh.iter {
s.map_chars(|c| ((c as uint) + 1) as char);
}
}
#[bench]
fn map_chars_100_multibytes(bh: &mut BenchHarness) {
let s = "𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑";
do bh.iter {
s.map_chars(|c| ((c as uint) + 1) as char);
}
}
#[bench]
fn bench_with_capacity(bh: &mut BenchHarness) {
do bh.iter {

View File

@ -149,7 +149,7 @@ impl AsciiCast<Ascii> for char {
#[inline]
fn is_ascii(&self) -> bool {
*self - ('\x7F' & *self) == '\x00'
*self as u32 - ('\x7F' as u32 & *self as u32) == 0
}
}
@ -380,6 +380,7 @@ static ASCII_UPPER_MAP: &'static [u8] = &[
mod tests {
use super::*;
use str::from_char;
use char::from_u32;
macro_rules! v2ascii (
( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
@ -469,9 +470,10 @@ mod tests {
let mut i = 0;
while i <= 500 {
let c = i as char;
let upper = if 'a' <= c && c <= 'z' { c + 'A' - 'a' } else { c };
assert_eq!(from_char(i as char).to_ascii_upper(), from_char(upper))
let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
else { i };
assert_eq!(from_char(from_u32(i).unwrap()).to_ascii_upper(),
from_char(from_u32(upper).unwrap()))
i += 1;
}
}
@ -484,9 +486,10 @@ mod tests {
let mut i = 0;
while i <= 500 {
let c = i as char;
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
assert_eq!(from_char(i as char).to_ascii_lower(), from_char(lower))
let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
else { i };
assert_eq!(from_char(from_u32(i).unwrap()).to_ascii_lower(),
from_char(from_u32(lower).unwrap()))
i += 1;
}
}
@ -503,9 +506,11 @@ mod tests {
let mut i = 0;
while i <= 500 {
let c = i as char;
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
assert!(from_char(i as char).eq_ignore_ascii_case(from_char(lower)));
let c = i;
let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 }
else { c };
assert!(from_char(from_u32(i).unwrap()).
eq_ignore_ascii_case(from_char(from_u32(lower).unwrap())));
i += 1;
}
}

View File

@ -56,14 +56,6 @@ pub mod general_category {
bsearch_range_table(c, Co_table)
}
static Cs_table : &'static [(char,char)] = &[
('\ud800', '\udfff')
];
pub fn Cs(c: char) -> bool {
bsearch_range_table(c, Cs_table)
}
static Ll_table : &'static [(char,char)] = &[
('\x61', '\x7a'), ('\xb5', '\xb5'),
('\xdf', '\xf6'), ('\xf8', '\xff'),

View File

@ -632,6 +632,7 @@ pub type lit = Spanned<lit_>;
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum lit_ {
lit_str(@str),
lit_char(u32),
lit_int(i64, int_ty),
lit_uint(u64, uint_ty),
lit_int_unsuffixed(i64),
@ -680,7 +681,6 @@ pub enum trait_method {
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum int_ty {
ty_i,
ty_char,
ty_i8,
ty_i16,
ty_i32,
@ -737,6 +737,7 @@ pub enum prim_ty {
ty_float(float_ty),
ty_str,
ty_bool,
ty_char
}
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]

View File

@ -151,7 +151,6 @@ pub fn is_path(e: @Expr) -> bool {
pub fn int_ty_to_str(t: int_ty) -> ~str {
match t {
ty_char => ~"u8", // ???
ty_i => ~"",
ty_i8 => ~"i8",
ty_i16 => ~"i16",
@ -164,7 +163,7 @@ pub fn int_ty_max(t: int_ty) -> u64 {
match t {
ty_i8 => 0x80u64,
ty_i16 => 0x8000u64,
ty_i | ty_char | ty_i32 => 0x80000000u64, // actually ni about ty_i
ty_i | ty_i32 => 0x80000000u64, // actually ni about ty_i
ty_i64 => 0x8000000000000000u64
}
}

View File

@ -16,6 +16,8 @@ use ext::base::*;
use ext::base;
use ext::build::AstBuilder;
use std::char;
pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) -> base::MacResult {
// Gather all argument expressions
let exprs = get_exprs_from_tts(cx, sp, tts);
@ -53,8 +55,8 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) -> bas
}
// char literal, push to vector expression
ast::lit_int(v, ast::ty_char) => {
if (v as char).is_ascii() {
ast::lit_char(v) => {
if char::from_u32(v).unwrap().is_ascii() {
bytes.push(cx.expr_u8(sp, v as u8));
} else {
cx.span_err(sp, "Non-ascii char literal in bytes!")

View File

@ -495,8 +495,7 @@ impl Context {
// Translate the format
let fill = match arg.format.fill { Some(c) => c, None => ' ' };
let fill = self.ecx.expr_lit(sp, ast::lit_int(fill as i64,
ast::ty_char));
let fill = self.ecx.expr_lit(sp, ast::lit_char(fill as u32));
let align = match arg.format.align {
parse::AlignLeft => {
self.ecx.path_global(sp, parsepath("AlignLeft"))

View File

@ -387,10 +387,18 @@ fn mk_token(cx: @ExtCtxt, sp: Span, tok: &token::Token) -> @ast::Expr {
~[mk_binop(cx, sp, binop)]);
}
LIT_CHAR(i) => {
let s_ity = ~"ty_char";
let e_ity = cx.expr_ident(sp, id_ext(s_ity));
let e_char = cx.expr_lit(sp, ast::lit_char(i));
return cx.expr_call_ident(sp, id_ext("LIT_CHAR"), ~[e_char, e_ity]);
}
LIT_INT(i, ity) => {
let s_ity = match ity {
ast::ty_i => ~"ty_i",
ast::ty_char => ~"ty_char",
ast::ty_i8 => ~"ty_i8",
ast::ty_i16 => ~"ty_i16",
ast::ty_i32 => ~"ty_i32",

View File

@ -17,6 +17,7 @@ use ext::tt::transcribe::{dup_tt_reader};
use parse::token;
use parse::token::{str_to_ident};
use std::cast::transmute;
use std::char;
use std::either;
use std::u64;
@ -184,7 +185,7 @@ pub fn bump(rdr: &mut StringReader) {
rdr.last_pos = rdr.pos;
let current_byte_offset = byte_offset(rdr, rdr.pos).to_uint();
if current_byte_offset < (rdr.src).len() {
assert!(rdr.curr != -1 as char);
assert!(rdr.curr != unsafe { transmute(-1u32) }); // FIXME: #8971: unsound
let last_char = rdr.curr;
let next = rdr.src.char_range_at(current_byte_offset);
let byte_offset_diff = next.next - current_byte_offset;
@ -201,17 +202,17 @@ pub fn bump(rdr: &mut StringReader) {
BytePos(current_byte_offset), byte_offset_diff);
}
} else {
rdr.curr = -1 as char;
rdr.curr = unsafe { transmute(-1u32) }; // FIXME: #8971: unsound
}
}
pub fn is_eof(rdr: @mut StringReader) -> bool {
rdr.curr == -1 as char
rdr.curr == unsafe { transmute(-1u32) } // FIXME: #8971: unsound
}
pub fn nextch(rdr: @mut StringReader) -> char {
let offset = byte_offset(rdr, rdr.pos).to_uint();
if offset < (rdr.src).len() {
return rdr.src.char_at(offset);
} else { return -1 as char; }
} else { return unsafe { transmute(-1u32) }; } // FIXME: #8971: unsound
}
fn dec_digit_val(c: char) -> int { return (c as int) - ('0' as int); }
@ -532,7 +533,10 @@ fn scan_numeric_escape(rdr: @mut StringReader, n_hex_digits: uint) -> char {
accum_int += hex_digit_val(n);
i -= 1u;
}
return accum_int as char;
match char::from_u32(accum_int as u32) {
Some(x) => x,
None => rdr.fatal(fmt!("illegal numeric character escape"))
}
}
fn ident_start(c: char) -> bool {
@ -707,7 +711,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
rdr.fatal(~"unterminated character constant");
}
bump(rdr); // advance curr past token
return token::LIT_INT(c2 as i64, ast::ty_char);
return token::LIT_CHAR(c2 as u32);
}
'"' => {
let mut accum_str = ~"";
@ -891,21 +895,21 @@ mod test {
let env = setup(@"'a'");
let TokenAndSpan {tok, sp: _} =
env.string_reader.next_token();
assert_eq!(tok,token::LIT_INT('a' as i64, ast::ty_char));
assert_eq!(tok,token::LIT_CHAR('a' as u32));
}
#[test] fn character_space() {
let env = setup(@"' '");
let TokenAndSpan {tok, sp: _} =
env.string_reader.next_token();
assert_eq!(tok, token::LIT_INT(' ' as i64, ast::ty_char));
assert_eq!(tok, token::LIT_CHAR(' ' as u32));
}
#[test] fn character_escaped() {
let env = setup(@"'\n'");
let TokenAndSpan {tok, sp: _} =
env.string_reader.next_token();
assert_eq!(tok, token::LIT_INT('\n' as i64, ast::ty_char));
assert_eq!(tok, token::LIT_CHAR('\n' as u32));
}
#[test] fn lifetime_name() {

View File

@ -37,7 +37,7 @@ use ast::{foreign_item, foreign_item_static, foreign_item_fn, foreign_mod};
use ast::{Ident, impure_fn, inherited, item, item_, item_static};
use ast::{item_enum, item_fn, item_foreign_mod, item_impl};
use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int};
use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int, lit_char};
use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local};
use ast::{MutImmutable, MutMutable, mac_, mac_invoc_tt, matcher, match_nonterminal};
use ast::{match_seq, match_tok, method, mt, BiMul, Mutability};
@ -1334,6 +1334,7 @@ impl Parser {
// matches token_lit = LIT_INT | ...
pub fn lit_from_token(&self, tok: &token::Token) -> lit_ {
match *tok {
token::LIT_CHAR(i) => lit_char(i),
token::LIT_INT(i, it) => lit_int(i, it),
token::LIT_UINT(u, ut) => lit_uint(u, ut),
token::LIT_INT_UNSUFFIXED(i) => lit_int_unsuffixed(i),

View File

@ -15,6 +15,7 @@ use parse::token;
use util::interner::StrInterner;
use util::interner;
use std::char;
use std::cmp::Equiv;
use std::local_data;
use std::rand;
@ -73,6 +74,7 @@ pub enum Token {
DOLLAR,
/* Literals */
LIT_CHAR(u32),
LIT_INT(i64, ast::int_ty),
LIT_UINT(u64, ast::uint_ty),
LIT_INT_UNSUFFIXED(i64),
@ -164,9 +166,9 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
DOLLAR => ~"$",
/* Literals */
LIT_INT(c, ast::ty_char) => {
LIT_CHAR(c) => {
let mut res = ~"'";
do (c as char).escape_default |c| {
do char::from_u32(c).unwrap().escape_default |c| {
res.push_char(c);
}
res.push_char('\'');
@ -236,6 +238,7 @@ pub fn can_begin_expr(t: &Token) -> bool {
IDENT(_, _) => true,
UNDERSCORE => true,
TILDE => true,
LIT_CHAR(_) => true,
LIT_INT(_, _) => true,
LIT_UINT(_, _) => true,
LIT_INT_UNSUFFIXED(_) => true,
@ -276,6 +279,7 @@ pub fn flip_delimiter(t: &token::Token) -> token::Token {
pub fn is_lit(t: &Token) -> bool {
match *t {
LIT_CHAR(_) => true,
LIT_INT(_, _) => true,
LIT_UINT(_, _) => true,
LIT_INT_UNSUFFIXED(_) => true,

View File

@ -27,6 +27,7 @@ use print::pp::{breaks, consistent, inconsistent, eof};
use print::pp;
use print::pprust;
use std::char;
use std::io;
// The @ps is stored here to prevent recursive type.
@ -2044,9 +2045,9 @@ pub fn print_literal(s: @ps, lit: &ast::lit) {
}
match lit.node {
ast::lit_str(st) => print_string(s, st),
ast::lit_int(ch, ast::ty_char) => {
ast::lit_char(ch) => {
let mut res = ~"'";
do (ch as char).escape_default |c| {
do char::from_u32(ch).unwrap().escape_default |c| {
res.push_char(c);
}
res.push_char('\'');

View File

@ -42,22 +42,6 @@ fn test_bool() {
assert_eq!(true ^ true, false);
}
fn test_char() {
let ch10 = 10 as char;
let ch4 = 4 as char;
let ch2 = 2 as char;
assert_eq!(ch10 + ch4, 14 as char);
assert_eq!(ch10 - ch4, 6 as char);
assert_eq!(ch10 * ch4, 40 as char);
assert_eq!(ch10 / ch4, ch2);
assert_eq!(ch10 % ch4, ch2);
assert_eq!(ch10 >> ch2, ch2);
assert_eq!(ch10 << ch4, 160 as char);
assert_eq!(ch10 | ch4, 14 as char);
assert_eq!(ch10 & ch2, ch2);
assert_eq!(ch10 ^ ch2, 8 as char);
}
fn test_box() {
assert_eq!(@10, @10);
}
@ -111,7 +95,6 @@ fn test_class() {
pub fn main() {
test_nil();
test_bool();
test_char();
test_box();
test_ptr();
test_class();

View File

@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// -*- rust -*-
pub fn main() {
let i: int = 'Q' as int;
@ -20,7 +17,7 @@ pub fn main() {
assert_eq!(u, 'Q' as u32);
assert_eq!(i as u8, 'Q' as u8);
assert_eq!(i as u8 as i8, 'Q' as u8 as i8);
assert_eq!(0x51 as char, 'Q');
assert_eq!(0x51u8 as char, 'Q');
assert_eq!(true, 1 as bool);
assert_eq!(0 as u32, false as u32);
}

View File

@ -18,7 +18,7 @@ pub fn main() {
}
fn test_misc() {
assert_eq!(1 << 1i8 << 1u8 << 1i16 << 1 as char << 1u64, 32);
assert_eq!(1 << 1i8 << 1u8 << 1i16 << 1u8 << 1u64, 32);
}
fn test_expr() {

View File

@ -14,7 +14,7 @@ use std::str;
pub fn main() {
// Chars of 1, 2, 3, and 4 bytes
let chs: ~[char] = ~['e', 'é', '€', 0x10000 as char];
let chs: ~[char] = ~['e', 'é', '€', '\U00010000'];
let s: ~str = str::from_chars(chs);
let schs: ~[char] = s.iter().collect();