auto merge of #11149 : alexcrichton/rust/remove-either, r=brson
Had to change some stuff in typeck to bootstrap (getting methods in fmt off of Either), but other than that not so painful. Closes #9157
This commit is contained in:
@@ -337,9 +337,14 @@ pub enum TestResult {
|
|||||||
TrBench(BenchSamples),
|
TrBench(BenchSamples),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum OutputLocation<T> {
|
||||||
|
Pretty(term::Terminal<T>),
|
||||||
|
Raw(T),
|
||||||
|
}
|
||||||
|
|
||||||
struct ConsoleTestState<T> {
|
struct ConsoleTestState<T> {
|
||||||
log_out: Option<File>,
|
log_out: Option<File>,
|
||||||
out: Either<term::Terminal<T>, T>,
|
out: OutputLocation<T>,
|
||||||
use_color: bool,
|
use_color: bool,
|
||||||
total: uint,
|
total: uint,
|
||||||
passed: uint,
|
passed: uint,
|
||||||
@@ -358,8 +363,8 @@ impl<T: Writer> ConsoleTestState<T> {
|
|||||||
None => None
|
None => None
|
||||||
};
|
};
|
||||||
let out = match term::Terminal::new(io::stdout()) {
|
let out = match term::Terminal::new(io::stdout()) {
|
||||||
Err(_) => Right(io::stdout()),
|
Err(_) => Raw(io::stdout()),
|
||||||
Ok(t) => Left(t)
|
Ok(t) => Pretty(t)
|
||||||
};
|
};
|
||||||
ConsoleTestState {
|
ConsoleTestState {
|
||||||
out: out,
|
out: out,
|
||||||
@@ -416,7 +421,7 @@ impl<T: Writer> ConsoleTestState<T> {
|
|||||||
word: &str,
|
word: &str,
|
||||||
color: term::color::Color) {
|
color: term::color::Color) {
|
||||||
match self.out {
|
match self.out {
|
||||||
Left(ref mut term) => {
|
Pretty(ref mut term) => {
|
||||||
if self.use_color {
|
if self.use_color {
|
||||||
term.fg(color);
|
term.fg(color);
|
||||||
}
|
}
|
||||||
@@ -425,14 +430,14 @@ impl<T: Writer> ConsoleTestState<T> {
|
|||||||
term.reset();
|
term.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Right(ref mut stdout) => stdout.write(word.as_bytes())
|
Raw(ref mut stdout) => stdout.write(word.as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_plain(&mut self, s: &str) {
|
pub fn write_plain(&mut self, s: &str) {
|
||||||
match self.out {
|
match self.out {
|
||||||
Left(ref mut term) => term.write(s.as_bytes()),
|
Pretty(ref mut term) => term.write(s.as_bytes()),
|
||||||
Right(ref mut stdout) => stdout.write(s.as_bytes())
|
Raw(ref mut stdout) => stdout.write(s.as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +688,7 @@ fn should_sort_failures_before_printing_them() {
|
|||||||
|
|
||||||
let mut st = ConsoleTestState {
|
let mut st = ConsoleTestState {
|
||||||
log_out: None,
|
log_out: None,
|
||||||
out: Right(MemWriter::new()),
|
out: Raw(MemWriter::new()),
|
||||||
use_color: false,
|
use_color: false,
|
||||||
total: 0u,
|
total: 0u,
|
||||||
passed: 0u,
|
passed: 0u,
|
||||||
@@ -697,8 +702,8 @@ fn should_sort_failures_before_printing_them() {
|
|||||||
|
|
||||||
st.write_failures();
|
st.write_failures();
|
||||||
let s = match st.out {
|
let s = match st.out {
|
||||||
Right(ref m) => str::from_utf8(*m.inner_ref()),
|
Raw(ref m) => str::from_utf8(*m.inner_ref()),
|
||||||
Left(_) => unreachable!()
|
Pretty(_) => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let apos = s.find_str("a").unwrap();
|
let apos = s.find_str("a").unwrap();
|
||||||
|
|||||||
@@ -1705,9 +1705,12 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
|||||||
fn_inputs.map(|a| *a)
|
fn_inputs.map(|a| *a)
|
||||||
} else {
|
} else {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"this function takes at least {0, plural, =1{# parameter} \
|
"this function takes at least {} parameter{} \
|
||||||
other{# parameters}} but {1, plural, =1{# parameter was} \
|
but {} parameter{} supplied",
|
||||||
other{# parameters were}} supplied", expected_arg_count, supplied_arg_count);
|
expected_arg_count,
|
||||||
|
if expected_arg_count == 1 {""} else {"s"},
|
||||||
|
supplied_arg_count,
|
||||||
|
if supplied_arg_count == 1 {" was"} else {"s were"});
|
||||||
|
|
||||||
tcx.sess.span_err(sp, msg);
|
tcx.sess.span_err(sp, msg);
|
||||||
|
|
||||||
@@ -1722,10 +1725,12 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
|||||||
the `for` keyword)"
|
the `for` keyword)"
|
||||||
};
|
};
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"this function takes {0, plural, =1{# parameter} \
|
"this function takes {} parameter{} \
|
||||||
other{# parameters}} but {1, plural, =1{# parameter was} \
|
but {} parameter{} supplied{}",
|
||||||
other{# parameters were}} supplied{2}",
|
expected_arg_count, if expected_arg_count == 1 {""} else {"s"},
|
||||||
expected_arg_count, supplied_arg_count, suffix);
|
supplied_arg_count,
|
||||||
|
if supplied_arg_count == 1 {" was"} else {"s were"},
|
||||||
|
suffix);
|
||||||
|
|
||||||
tcx.sess.span_err(sp, msg);
|
tcx.sess.span_err(sp, msg);
|
||||||
|
|
||||||
|
|||||||
@@ -1,248 +0,0 @@
|
|||||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
//! Representing values with two possibilities (`Either` type)
|
|
||||||
|
|
||||||
#[allow(missing_doc)];
|
|
||||||
|
|
||||||
use option::{Some, None};
|
|
||||||
use clone::Clone;
|
|
||||||
use container::Container;
|
|
||||||
use cmp::Eq;
|
|
||||||
use iter::{Iterator, FilterMap};
|
|
||||||
use str::StrSlice;
|
|
||||||
use vec;
|
|
||||||
use vec::{OwnedVector, ImmutableVector};
|
|
||||||
|
|
||||||
/// `Either` is a type that represents one of two alternatives
|
|
||||||
#[deriving(Clone, Eq, IterBytes)]
|
|
||||||
pub enum Either<L, R> {
|
|
||||||
Left(L),
|
|
||||||
Right(R)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L, R> Either<L, R> {
|
|
||||||
/// Applies a function based on the given either value
|
|
||||||
///
|
|
||||||
/// If `value` is `Left(L)` then `f_left` is applied to its contents, if
|
|
||||||
/// `value` is `Right(R)` then `f_right` is applied to its contents, and the
|
|
||||||
/// result is returned.
|
|
||||||
#[inline]
|
|
||||||
pub fn either<T>(&self, f_left: |&L| -> T, f_right: |&R| -> T) -> T {
|
|
||||||
match *self {
|
|
||||||
Left(ref l) => f_left(l),
|
|
||||||
Right(ref r) => f_right(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Flips between left and right of a given `Either`
|
|
||||||
#[inline]
|
|
||||||
pub fn flip(self) -> Either<R, L> {
|
|
||||||
match self {
|
|
||||||
Right(r) => Left(r),
|
|
||||||
Left(l) => Right(l)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks whether the given value is a `Left`
|
|
||||||
#[inline]
|
|
||||||
pub fn is_left(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Left(_) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks whether the given value is a `Right`
|
|
||||||
#[inline]
|
|
||||||
pub fn is_right(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Right(_) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the value from a `Left`.
|
|
||||||
/// Fails with a specified reason if the `Either` is `Right`.
|
|
||||||
#[inline]
|
|
||||||
pub fn expect_left(self, reason: &str) -> L {
|
|
||||||
match self {
|
|
||||||
Left(x) => x,
|
|
||||||
Right(_) => fail!("{}", reason.to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the value from a `Left`. Fails if the `Either` is `Right`.
|
|
||||||
#[inline]
|
|
||||||
pub fn unwrap_left(self) -> L {
|
|
||||||
self.expect_left("called Either::unwrap_left()` on `Right` value")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the value from a `Right`.
|
|
||||||
/// Fails with a specified reason if the `Either` is `Left`.
|
|
||||||
#[inline]
|
|
||||||
pub fn expect_right(self, reason: &str) -> R {
|
|
||||||
match self {
|
|
||||||
Right(x) => x,
|
|
||||||
Left(_) => fail!("{}", reason.to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the value from a `Right`. Fails if the `Either` is `Left`.
|
|
||||||
#[inline]
|
|
||||||
pub fn unwrap_right(self) -> R {
|
|
||||||
self.expect_right("called Either::unwrap_right()` on `Left` value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An iterator yielding the `Left` values of its source
|
|
||||||
pub type Lefts<L, R, Iter> = FilterMap<'static, Either<L, R>, L, Iter>;
|
|
||||||
|
|
||||||
/// An iterator yielding the `Right` values of its source
|
|
||||||
pub type Rights<L, R, Iter> = FilterMap<'static, Either<L, R>, R, Iter>;
|
|
||||||
|
|
||||||
/// Extracts all the left values
|
|
||||||
pub fn lefts<L, R, Iter: Iterator<Either<L, R>>>(eithers: Iter)
|
|
||||||
-> Lefts<L, R, Iter> {
|
|
||||||
eithers.filter_map(|elt| {
|
|
||||||
match elt {
|
|
||||||
Left(x) => Some(x),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extracts all the right values
|
|
||||||
pub fn rights<L, R, Iter: Iterator<Either<L, R>>>(eithers: Iter)
|
|
||||||
-> Rights<L, R, Iter> {
|
|
||||||
eithers.filter_map(|elt| {
|
|
||||||
match elt {
|
|
||||||
Right(x) => Some(x),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: #8228 Replaceable by an external iterator?
|
|
||||||
/// Extracts from a vector of either all the left values and right values
|
|
||||||
///
|
|
||||||
/// Returns a structure containing a vector of left values and a vector of
|
|
||||||
/// right values.
|
|
||||||
pub fn partition<L, R>(eithers: ~[Either<L, R>]) -> (~[L], ~[R]) {
|
|
||||||
let n_lefts = eithers.iter().count(|elt| elt.is_left());
|
|
||||||
let mut lefts = vec::with_capacity(n_lefts);
|
|
||||||
let mut rights = vec::with_capacity(eithers.len() - n_lefts);
|
|
||||||
for elt in eithers.move_iter() {
|
|
||||||
match elt {
|
|
||||||
Left(l) => lefts.push(l),
|
|
||||||
Right(r) => rights.push(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (lefts, rights);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_either_left() {
|
|
||||||
let val = Left(10);
|
|
||||||
fn f_left(x: &int) -> bool { *x == 10 }
|
|
||||||
fn f_right(_x: &uint) -> bool { false }
|
|
||||||
assert!(val.either(f_left, f_right));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_either_right() {
|
|
||||||
let val = Right(10u);
|
|
||||||
fn f_left(_x: &int) -> bool { false }
|
|
||||||
fn f_right(x: &uint) -> bool { *x == 10u }
|
|
||||||
assert!(val.either(f_left, f_right));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_lefts() {
|
|
||||||
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
|
||||||
let result = lefts(input.move_iter()).to_owned_vec();
|
|
||||||
assert_eq!(result, ~[10, 12, 14]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_lefts_none() {
|
|
||||||
let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
|
|
||||||
let result = lefts(input.move_iter()).to_owned_vec();
|
|
||||||
assert_eq!(result.len(), 0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_lefts_empty() {
|
|
||||||
let input: ~[Either<int, int>] = ~[];
|
|
||||||
let result = lefts(input.move_iter()).to_owned_vec();
|
|
||||||
assert_eq!(result.len(), 0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rights() {
|
|
||||||
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
|
||||||
let result = rights(input.move_iter()).to_owned_vec();
|
|
||||||
assert_eq!(result, ~[11, 13]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rights_none() {
|
|
||||||
let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
|
|
||||||
let result = rights(input.move_iter()).to_owned_vec();
|
|
||||||
assert_eq!(result.len(), 0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rights_empty() {
|
|
||||||
let input: ~[Either<int, int>] = ~[];
|
|
||||||
let result = rights(input.move_iter()).to_owned_vec();
|
|
||||||
assert_eq!(result.len(), 0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_partition() {
|
|
||||||
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
|
||||||
let (lefts, rights) = partition(input);
|
|
||||||
assert_eq!(lefts[0], 10);
|
|
||||||
assert_eq!(lefts[1], 12);
|
|
||||||
assert_eq!(lefts[2], 14);
|
|
||||||
assert_eq!(rights[0], 11);
|
|
||||||
assert_eq!(rights[1], 13);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_partition_no_lefts() {
|
|
||||||
let input: ~[Either<int, int>] = ~[Right(10), Right(11)];
|
|
||||||
let (lefts, rights) = partition(input);
|
|
||||||
assert_eq!(lefts.len(), 0u);
|
|
||||||
assert_eq!(rights.len(), 2u);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_partition_no_rights() {
|
|
||||||
let input: ~[Either<int, int>] = ~[Left(10), Left(11)];
|
|
||||||
let (lefts, rights) = partition(input);
|
|
||||||
assert_eq!(lefts.len(), 2u);
|
|
||||||
assert_eq!(rights.len(), 0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_partition_empty() {
|
|
||||||
let input: ~[Either<int, int>] = ~[];
|
|
||||||
let (lefts, rights) = partition(input);
|
|
||||||
assert_eq!(lefts.len(), 0u);
|
|
||||||
assert_eq!(rights.len(), 0u);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -757,7 +757,7 @@ impl<'a> Formatter<'a> {
|
|||||||
// offsetted value
|
// offsetted value
|
||||||
for s in selectors.iter() {
|
for s in selectors.iter() {
|
||||||
match s.selector {
|
match s.selector {
|
||||||
Right(val) if value == val => {
|
rt::Literal(val) if value == val => {
|
||||||
return self.runplural(value, s.result);
|
return self.runplural(value, s.result);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -769,17 +769,17 @@ impl<'a> Formatter<'a> {
|
|||||||
let value = value - match offset { Some(i) => i, None => 0 };
|
let value = value - match offset { Some(i) => i, None => 0 };
|
||||||
for s in selectors.iter() {
|
for s in selectors.iter() {
|
||||||
let run = match s.selector {
|
let run = match s.selector {
|
||||||
Left(parse::Zero) => value == 0,
|
rt::Keyword(parse::Zero) => value == 0,
|
||||||
Left(parse::One) => value == 1,
|
rt::Keyword(parse::One) => value == 1,
|
||||||
Left(parse::Two) => value == 2,
|
rt::Keyword(parse::Two) => value == 2,
|
||||||
|
|
||||||
// XXX: Few/Many should have a user-specified boundary
|
// XXX: Few/Many should have a user-specified boundary
|
||||||
// One possible option would be in the function
|
// One possible option would be in the function
|
||||||
// pointer of the 'arg: Argument' struct.
|
// pointer of the 'arg: Argument' struct.
|
||||||
Left(parse::Few) => value < 8,
|
rt::Keyword(parse::Few) => value < 8,
|
||||||
Left(parse::Many) => value >= 8,
|
rt::Keyword(parse::Many) => value >= 8,
|
||||||
|
|
||||||
Right(..) => false
|
rt::Literal(..) => false
|
||||||
};
|
};
|
||||||
if run {
|
if run {
|
||||||
return self.runplural(value, s.result);
|
return self.runplural(value, s.result);
|
||||||
|
|||||||
@@ -122,12 +122,21 @@ pub enum Method<'a> {
|
|||||||
Select(~[SelectArm<'a>], ~[Piece<'a>]),
|
Select(~[SelectArm<'a>], ~[Piece<'a>]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A selector for what pluralization a plural method should take
|
||||||
|
#[deriving(Eq, IterBytes)]
|
||||||
|
pub enum PluralSelector {
|
||||||
|
/// One of the plural keywords should be used
|
||||||
|
Keyword(PluralKeyword),
|
||||||
|
/// A literal pluralization should be used
|
||||||
|
Literal(uint),
|
||||||
|
}
|
||||||
|
|
||||||
/// Structure representing one "arm" of the `plural` function.
|
/// Structure representing one "arm" of the `plural` function.
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
pub struct PluralArm<'a> {
|
pub struct PluralArm<'a> {
|
||||||
/// A selector can either be specified by a keyword or with an integer
|
/// A selector can either be specified by a keyword or with an integer
|
||||||
/// literal.
|
/// literal.
|
||||||
selector: Either<PluralKeyword, uint>,
|
selector: PluralSelector,
|
||||||
/// Array of pieces which are the format of this arm
|
/// Array of pieces which are the format of this arm
|
||||||
result: ~[Piece<'a>],
|
result: ~[Piece<'a>],
|
||||||
}
|
}
|
||||||
@@ -504,29 +513,29 @@ impl<'a> Parser<'a> {
|
|||||||
let mut isother = false;
|
let mut isother = false;
|
||||||
let selector = if self.wsconsume('=') {
|
let selector = if self.wsconsume('=') {
|
||||||
match self.integer() {
|
match self.integer() {
|
||||||
Some(i) => Right(i),
|
Some(i) => Literal(i),
|
||||||
None => {
|
None => {
|
||||||
self.err("plural `=` selectors must be followed by an \
|
self.err("plural `=` selectors must be followed by an \
|
||||||
integer");
|
integer");
|
||||||
Right(0)
|
Literal(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let word = self.word();
|
let word = self.word();
|
||||||
match word {
|
match word {
|
||||||
"other" => { isother = true; Left(Zero) }
|
"other" => { isother = true; Keyword(Zero) }
|
||||||
"zero" => Left(Zero),
|
"zero" => Keyword(Zero),
|
||||||
"one" => Left(One),
|
"one" => Keyword(One),
|
||||||
"two" => Left(Two),
|
"two" => Keyword(Two),
|
||||||
"few" => Left(Few),
|
"few" => Keyword(Few),
|
||||||
"many" => Left(Many),
|
"many" => Keyword(Many),
|
||||||
word => {
|
word => {
|
||||||
self.err(format!("unexpected plural selector `{}`",
|
self.err(format!("unexpected plural selector `{}`",
|
||||||
word));
|
word));
|
||||||
if word == "" {
|
if word == "" {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
Left(Zero)
|
Keyword(Zero)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -955,9 +964,9 @@ mod tests {
|
|||||||
position: ArgumentNext,
|
position: ArgumentNext,
|
||||||
format: fmtdflt(),
|
format: fmtdflt(),
|
||||||
method: Some(~Plural(Some(1), ~[
|
method: Some(~Plural(Some(1), ~[
|
||||||
PluralArm{ selector: Right(2), result: ~[String("2")] },
|
PluralArm{ selector: Literal(2), result: ~[String("2")] },
|
||||||
PluralArm{ selector: Right(3), result: ~[String("3")] },
|
PluralArm{ selector: Literal(3), result: ~[String("3")] },
|
||||||
PluralArm{ selector: Left(Many), result: ~[String("yes")] }
|
PluralArm{ selector: Keyword(Many), result: ~[String("yes")] }
|
||||||
], ~[String("haha")]))
|
], ~[String("haha")]))
|
||||||
})]);
|
})]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#[allow(missing_doc)];
|
#[allow(missing_doc)];
|
||||||
#[doc(hidden)];
|
#[doc(hidden)];
|
||||||
|
|
||||||
use either::Either;
|
|
||||||
use fmt::parse;
|
use fmt::parse;
|
||||||
use option::Option;
|
use option::Option;
|
||||||
|
|
||||||
@@ -55,8 +54,13 @@ pub enum Method<'a> {
|
|||||||
Select(&'a [SelectArm<'a>], &'a [Piece<'a>]),
|
Select(&'a [SelectArm<'a>], &'a [Piece<'a>]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum PluralSelector {
|
||||||
|
Keyword(parse::PluralKeyword),
|
||||||
|
Literal(uint),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PluralArm<'a> {
|
pub struct PluralArm<'a> {
|
||||||
selector: Either<parse::PluralKeyword, uint>,
|
selector: PluralSelector,
|
||||||
result: &'a [Piece<'a>],
|
result: &'a [Piece<'a>],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ pub mod any;
|
|||||||
|
|
||||||
pub mod option;
|
pub mod option;
|
||||||
pub mod result;
|
pub mod result;
|
||||||
pub mod either;
|
|
||||||
pub mod hashmap;
|
pub mod hashmap;
|
||||||
pub mod cell;
|
pub mod cell;
|
||||||
pub mod trie;
|
pub mod trie;
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ Rust's prelude has three main parts:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Reexported core operators
|
// Reexported core operators
|
||||||
pub use either::{Either, Left, Right};
|
|
||||||
pub use kinds::{Freeze, Pod, Send, Sized};
|
pub use kinds::{Freeze, Pod, Send, Sized};
|
||||||
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
|
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
|
||||||
pub use ops::{BitAnd, BitOr, BitXor};
|
pub use ops::{BitAnd, BitOr, BitXor};
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ mod tests {
|
|||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use option::{None, Some};
|
use option::{None, Some};
|
||||||
use either::{Either, Left, Right};
|
|
||||||
use mem::size_of;
|
use mem::size_of;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -111,15 +110,6 @@ mod tests {
|
|||||||
assert!(y.is_some());
|
assert!(y.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_uninhabited() {
|
|
||||||
let could_only_be_coin : Either <Void, ()> = Right (());
|
|
||||||
match could_only_be_coin {
|
|
||||||
Right (coin) => coin,
|
|
||||||
Left (is_void) => is_void.uninhabited ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_noncopyable() {
|
fn test_noncopyable() {
|
||||||
assert_eq!(size_of::<NonCopyable>(), 0);
|
assert_eq!(size_of::<NonCopyable>(), 0);
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ enum ArgumentType {
|
|||||||
String,
|
String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Position {
|
||||||
|
Exact(uint),
|
||||||
|
Named(@str),
|
||||||
|
}
|
||||||
|
|
||||||
struct Context<'a> {
|
struct Context<'a> {
|
||||||
ecx: &'a mut ExtCtxt,
|
ecx: &'a mut ExtCtxt,
|
||||||
fmtsp: Span,
|
fmtsp: Span,
|
||||||
@@ -148,10 +153,10 @@ impl<'a> Context<'a> {
|
|||||||
if self.check_positional_ok() {
|
if self.check_positional_ok() {
|
||||||
self.next_arg += 1;
|
self.next_arg += 1;
|
||||||
}
|
}
|
||||||
Left(i)
|
Exact(i)
|
||||||
}
|
}
|
||||||
parse::ArgumentIs(i) => Left(i),
|
parse::ArgumentIs(i) => Exact(i),
|
||||||
parse::ArgumentNamed(s) => Right(s.to_managed()),
|
parse::ArgumentNamed(s) => Named(s.to_managed()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// and finally the method being applied
|
// and finally the method being applied
|
||||||
@@ -176,14 +181,14 @@ impl<'a> Context<'a> {
|
|||||||
match c {
|
match c {
|
||||||
parse::CountImplied | parse::CountIs(..) => {}
|
parse::CountImplied | parse::CountIs(..) => {}
|
||||||
parse::CountIsParam(i) => {
|
parse::CountIsParam(i) => {
|
||||||
self.verify_arg_type(Left(i), Unsigned);
|
self.verify_arg_type(Exact(i), Unsigned);
|
||||||
}
|
}
|
||||||
parse::CountIsName(s) => {
|
parse::CountIsName(s) => {
|
||||||
self.verify_arg_type(Right(s.to_managed()), Unsigned);
|
self.verify_arg_type(Named(s.to_managed()), Unsigned);
|
||||||
}
|
}
|
||||||
parse::CountIsNextParam => {
|
parse::CountIsNextParam => {
|
||||||
if self.check_positional_ok() {
|
if self.check_positional_ok() {
|
||||||
self.verify_arg_type(Left(self.next_arg), Unsigned);
|
self.verify_arg_type(Exact(self.next_arg), Unsigned);
|
||||||
self.next_arg += 1;
|
self.next_arg += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,7 +205,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_method(&mut self, pos: Either<uint, @str>, m: &parse::Method) {
|
fn verify_method(&mut self, pos: Position, m: &parse::Method) {
|
||||||
self.nest_level += 1;
|
self.nest_level += 1;
|
||||||
match *m {
|
match *m {
|
||||||
parse::Plural(_, ref arms, ref default) => {
|
parse::Plural(_, ref arms, ref default) => {
|
||||||
@@ -209,12 +214,12 @@ impl<'a> Context<'a> {
|
|||||||
for arm in arms.iter() {
|
for arm in arms.iter() {
|
||||||
if !seen_cases.insert(arm.selector) {
|
if !seen_cases.insert(arm.selector) {
|
||||||
match arm.selector {
|
match arm.selector {
|
||||||
Left(name) => {
|
parse::Keyword(name) => {
|
||||||
self.ecx.span_err(self.fmtsp,
|
self.ecx.span_err(self.fmtsp,
|
||||||
format!("duplicate selector \
|
format!("duplicate selector \
|
||||||
`{:?}`", name));
|
`{:?}`", name));
|
||||||
}
|
}
|
||||||
Right(idx) => {
|
parse::Literal(idx) => {
|
||||||
self.ecx.span_err(self.fmtsp,
|
self.ecx.span_err(self.fmtsp,
|
||||||
format!("duplicate selector \
|
format!("duplicate selector \
|
||||||
`={}`", idx));
|
`={}`", idx));
|
||||||
@@ -245,9 +250,9 @@ impl<'a> Context<'a> {
|
|||||||
self.nest_level -= 1;
|
self.nest_level -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_arg_type(&mut self, arg: Either<uint, @str>, ty: ArgumentType) {
|
fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
|
||||||
match arg {
|
match arg {
|
||||||
Left(arg) => {
|
Exact(arg) => {
|
||||||
if arg < 0 || self.args.len() <= arg {
|
if arg < 0 || self.args.len() <= arg {
|
||||||
let msg = format!("invalid reference to argument `{}` (there \
|
let msg = format!("invalid reference to argument `{}` (there \
|
||||||
are {} arguments)", arg, self.args.len());
|
are {} arguments)", arg, self.args.len());
|
||||||
@@ -260,7 +265,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Right(name) => {
|
Named(name) => {
|
||||||
let span = match self.names.find(&name) {
|
let span = match self.names.find(&name) {
|
||||||
Some(e) => e.span,
|
Some(e) => e.span,
|
||||||
None => {
|
None => {
|
||||||
@@ -434,18 +439,16 @@ impl<'a> Context<'a> {
|
|||||||
self.trans_piece(p)
|
self.trans_piece(p)
|
||||||
}).collect();
|
}).collect();
|
||||||
let (lr, selarg) = match arm.selector {
|
let (lr, selarg) = match arm.selector {
|
||||||
Left(t) => {
|
parse::Keyword(t) => {
|
||||||
let p = ctpath(format!("{:?}", t));
|
let p = ctpath(format!("{:?}", t));
|
||||||
let p = self.ecx.path_global(sp, p);
|
let p = self.ecx.path_global(sp, p);
|
||||||
(self.ecx.ident_of("Left"),
|
(rtpath("Keyword"), self.ecx.expr_path(p))
|
||||||
self.ecx.expr_path(p))
|
|
||||||
}
|
}
|
||||||
Right(i) => {
|
parse::Literal(i) => {
|
||||||
(self.ecx.ident_of("Right"),
|
(rtpath("Literal"), self.ecx.expr_uint(sp, i))
|
||||||
self.ecx.expr_uint(sp, i))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let selector = self.ecx.expr_call_ident(sp,
|
let selector = self.ecx.expr_call_global(sp,
|
||||||
lr, ~[selarg]);
|
lr, ~[selarg]);
|
||||||
self.ecx.expr_struct(sp, p, ~[
|
self.ecx.expr_struct(sp, p, ~[
|
||||||
self.ecx.field_imm(sp,
|
self.ecx.field_imm(sp,
|
||||||
@@ -617,7 +620,7 @@ impl<'a> Context<'a> {
|
|||||||
let name = self.ecx.ident_of(format!("__arg{}", i));
|
let name = self.ecx.ident_of(format!("__arg{}", i));
|
||||||
let e = self.ecx.expr_addr_of(e.span, e);
|
let e = self.ecx.expr_addr_of(e.span, e);
|
||||||
lets.push(self.ecx.stmt_let(e.span, false, name, e));
|
lets.push(self.ecx.stmt_let(e.span, false, name, e));
|
||||||
locals.push(self.format_arg(e.span, Left(i),
|
locals.push(self.format_arg(e.span, Exact(i),
|
||||||
self.ecx.expr_ident(e.span, name)));
|
self.ecx.expr_ident(e.span, name)));
|
||||||
}
|
}
|
||||||
for (&name, &e) in self.names.iter() {
|
for (&name, &e) in self.names.iter() {
|
||||||
@@ -627,7 +630,7 @@ impl<'a> Context<'a> {
|
|||||||
let e = self.ecx.expr_addr_of(e.span, e);
|
let e = self.ecx.expr_addr_of(e.span, e);
|
||||||
lets.push(self.ecx.stmt_let(e.span, false, lname, e));
|
lets.push(self.ecx.stmt_let(e.span, false, lname, e));
|
||||||
names[*self.name_positions.get(&name)] =
|
names[*self.name_positions.get(&name)] =
|
||||||
Some(self.format_arg(e.span, Right(name),
|
Some(self.format_arg(e.span, Named(name),
|
||||||
self.ecx.expr_ident(e.span, lname)));
|
self.ecx.expr_ident(e.span, lname)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,11 +665,11 @@ impl<'a> Context<'a> {
|
|||||||
Some(result)))
|
Some(result)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_arg(&self, sp: Span, argno: Either<uint, @str>,
|
fn format_arg(&self, sp: Span, argno: Position,
|
||||||
arg: @ast::Expr) -> @ast::Expr {
|
arg: @ast::Expr) -> @ast::Expr {
|
||||||
let ty = match argno {
|
let ty = match argno {
|
||||||
Left(i) => self.arg_types[i].unwrap(),
|
Exact(i) => self.arg_types[i].unwrap(),
|
||||||
Right(s) => *self.name_types.get(&s)
|
Named(s) => *self.name_types.get(&s)
|
||||||
};
|
};
|
||||||
|
|
||||||
let fmt_trait = match ty {
|
let fmt_trait = match ty {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use parse::token::{str_to_ident};
|
|||||||
|
|
||||||
use std::cast::transmute;
|
use std::cast::transmute;
|
||||||
use std::char;
|
use std::char;
|
||||||
use std::either;
|
|
||||||
use std::num::from_str_radix;
|
use std::num::from_str_radix;
|
||||||
use std::util;
|
use std::util;
|
||||||
|
|
||||||
@@ -475,34 +474,35 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
|
|||||||
c = rdr.curr;
|
c = rdr.curr;
|
||||||
nextch(rdr);
|
nextch(rdr);
|
||||||
if c == 'u' || c == 'i' {
|
if c == 'u' || c == 'i' {
|
||||||
|
enum Result { Signed(ast::int_ty), Unsigned(ast::uint_ty) }
|
||||||
let signed = c == 'i';
|
let signed = c == 'i';
|
||||||
let mut tp = {
|
let mut tp = {
|
||||||
if signed { either::Left(ast::ty_i) }
|
if signed { Signed(ast::ty_i) }
|
||||||
else { either::Right(ast::ty_u) }
|
else { Unsigned(ast::ty_u) }
|
||||||
};
|
};
|
||||||
bump(rdr);
|
bump(rdr);
|
||||||
c = rdr.curr;
|
c = rdr.curr;
|
||||||
if c == '8' {
|
if c == '8' {
|
||||||
bump(rdr);
|
bump(rdr);
|
||||||
tp = if signed { either::Left(ast::ty_i8) }
|
tp = if signed { Signed(ast::ty_i8) }
|
||||||
else { either::Right(ast::ty_u8) };
|
else { Unsigned(ast::ty_u8) };
|
||||||
}
|
}
|
||||||
n = nextch(rdr);
|
n = nextch(rdr);
|
||||||
if c == '1' && n == '6' {
|
if c == '1' && n == '6' {
|
||||||
bump(rdr);
|
bump(rdr);
|
||||||
bump(rdr);
|
bump(rdr);
|
||||||
tp = if signed { either::Left(ast::ty_i16) }
|
tp = if signed { Signed(ast::ty_i16) }
|
||||||
else { either::Right(ast::ty_u16) };
|
else { Unsigned(ast::ty_u16) };
|
||||||
} else if c == '3' && n == '2' {
|
} else if c == '3' && n == '2' {
|
||||||
bump(rdr);
|
bump(rdr);
|
||||||
bump(rdr);
|
bump(rdr);
|
||||||
tp = if signed { either::Left(ast::ty_i32) }
|
tp = if signed { Signed(ast::ty_i32) }
|
||||||
else { either::Right(ast::ty_u32) };
|
else { Unsigned(ast::ty_u32) };
|
||||||
} else if c == '6' && n == '4' {
|
} else if c == '6' && n == '4' {
|
||||||
bump(rdr);
|
bump(rdr);
|
||||||
bump(rdr);
|
bump(rdr);
|
||||||
tp = if signed { either::Left(ast::ty_i64) }
|
tp = if signed { Signed(ast::ty_i64) }
|
||||||
else { either::Right(ast::ty_u64) };
|
else { Unsigned(ast::ty_u64) };
|
||||||
}
|
}
|
||||||
if num_str.len() == 0u {
|
if num_str.len() == 0u {
|
||||||
fatal_span(rdr, start_bpos, rdr.last_pos,
|
fatal_span(rdr, start_bpos, rdr.last_pos,
|
||||||
@@ -515,8 +515,8 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match tp {
|
match tp {
|
||||||
either::Left(t) => return token::LIT_INT(parsed as i64, t),
|
Signed(t) => return token::LIT_INT(parsed as i64, t),
|
||||||
either::Right(t) => return token::LIT_UINT(parsed, t)
|
Unsigned(t) => return token::LIT_UINT(parsed, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut is_float = false;
|
let mut is_float = false;
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
enum Either<T, U> { Left(T), Right(U) }
|
||||||
|
|
||||||
struct X(Either<(uint,uint),extern fn()>);
|
struct X(Either<(uint,uint),extern fn()>);
|
||||||
|
|
||||||
impl X {
|
impl X {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::either::{Either, Left, Right};
|
enum Either<T, U> { Left(T), Right(U) }
|
||||||
|
|
||||||
fn f(x: &mut Either<int,f64>, y: &Either<int,f64>) -> int {
|
fn f(x: &mut Either<int,f64>, y: &Either<int,f64>) -> int {
|
||||||
match *y {
|
match *y {
|
||||||
|
|||||||
@@ -8,11 +8,12 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
enum Either<T, U> { Left(T), Right(U) }
|
||||||
struct S(Either<uint, uint>);
|
struct S(Either<uint, uint>);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match S(Left(5)) {
|
match S(Left(5)) {
|
||||||
Right(_) => {} //~ ERROR mismatched types: expected `S` but found `std::either::Either
|
Right(_) => {} //~ ERROR mismatched types: expected `S` but found `Either
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,11 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
enum Either<T, U> { Left(T), Right(U) }
|
||||||
struct S(Either<uint, uint>);
|
struct S(Either<uint, uint>);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match *S(Left(5)) {
|
match *S(Left(5)) {
|
||||||
S(_) => {} //~ ERROR mismatched types: expected `std::either::Either<uint,uint>` but found a structure pattern
|
S(_) => {} //~ ERROR mismatched types: expected `Either<uint,uint>` but found a structure pattern
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
use cal = bar::c::cc;
|
use cal = bar::c::cc;
|
||||||
|
|
||||||
use std::either::Right; //~ ERROR unused import
|
|
||||||
|
|
||||||
use std::util::*; // shouldn't get errors for not using
|
use std::util::*; // shouldn't get errors for not using
|
||||||
// everything imported
|
// everything imported
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#[feature(managed_boxes)];
|
#[feature(managed_boxes)];
|
||||||
|
|
||||||
|
enum Either<T, U> { Left(T), Right(U) }
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
match Left(@17) {
|
match Left(@17) {
|
||||||
Right(()) => {}
|
Right(()) => {}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
|
||||||
|
#[deriving(Eq)]
|
||||||
|
enum Either<T, U> { Left(T), Right(U) }
|
||||||
|
|
||||||
macro_rules! check {
|
macro_rules! check {
|
||||||
($t:ty, $sz:expr, $($e:expr, $s:expr),*) => {{
|
($t:ty, $sz:expr, $($e:expr, $s:expr),*) => {{
|
||||||
assert_eq!(size_of::<$t>(), $sz);
|
assert_eq!(size_of::<$t>(), $sz);
|
||||||
|
|||||||
Reference in New Issue
Block a user