From 612553cb3921f428668602afda1b106e0fd54d73 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Sun, 17 Feb 2013 15:41:47 -0800 Subject: syntax: Allow 1-tuple expressions This is for greater uniformity (for example, macros that generate tuples). rustc already supported 1-tuple patterns, but there was no way to construct a 1-tuple term. --- src/libsyntax/parse/parser.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 799f0d40a46..b5c68d6715e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1061,6 +1061,9 @@ pub impl Parser { if self.token == token::LPAREN { self.bump(); + // (e) is parenthesized e + // (e,) is a tuple with only one field, e + let mut one_tuple = false; if self.token == token::RPAREN { hi = self.span.hi; self.bump(); @@ -1069,12 +1072,18 @@ pub impl Parser { } let mut es = ~[self.parse_expr()]; while self.token == token::COMMA { - self.bump(); es.push(self.parse_expr()); + self.bump(); + if self.token != token::RPAREN { + es.push(self.parse_expr()); + } + else { + one_tuple = true; + } } hi = self.span.hi; self.expect(token::RPAREN); - return if es.len() == 1 { + return if es.len() == 1 && !one_tuple { self.mk_expr(lo, self.span.hi, expr_paren(es[0])) } else { @@ -2158,11 +2167,13 @@ pub impl Parser { pat = pat_lit(expr); } else { let mut fields = ~[self.parse_pat(refutable)]; - while self.token == token::COMMA { - self.bump(); - fields.push(self.parse_pat(refutable)); + if self.look_ahead(1) != token::RPAREN { + while self.token == token::COMMA { + self.bump(); + fields.push(self.parse_pat(refutable)); + } } - if vec::len(fields) == 1u { self.expect(token::COMMA); } + if fields.len() == 1 { self.expect(token::COMMA); } hi = self.span.hi; self.expect(token::RPAREN); pat = pat_tup(fields); -- cgit 1.4.1-3-g733a5 From aa284de1fc246b55fb53783ded3e9786e04b03d0 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 18 Feb 2013 17:45:56 -0800 Subject: rustc: For one-tuples, make parsing and printing the type work and add a test to reflect-visit-data --- src/libcore/to_str.rs | 2 ++ src/libcore/tuple.rs | 2 ++ src/libsyntax/parse/parser.rs | 13 +++++++++++-- src/libsyntax/print/pprust.rs | 3 +++ src/test/run-pass/one-tuple.rs | 4 ++++ src/test/run-pass/reflect-visit-data.rs | 7 ++++--- 6 files changed, 26 insertions(+), 5 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index e545f6567ec..4cccc1d2638 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -43,6 +43,8 @@ impl ToStr for @str { pure fn to_str(&self) -> ~str { ::str::from_slice(*self) } } +// FIXME #4898: impl for one-tuples + impl ToStr for (A, B) { #[inline(always)] pure fn to_str(&self) -> ~str { diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 23235104e9f..e49c1d26a06 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -111,6 +111,8 @@ impl ExtendedTupleOps for (~[A], ~[B]) { } } +// FIXME #4898: impl for one-tuples + #[cfg(notest)] impl Eq for (A, B) { #[inline(always)] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b5c68d6715e..a9b455c3304 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -576,12 +576,21 @@ pub impl Parser { self.bump(); ty_nil } else { + // (t) is a parenthesized ty + // (t,) is the type of a tuple with only one field, + // of type t let mut ts = ~[self.parse_ty(false)]; + let mut one_tuple = false; while self.token == token::COMMA { self.bump(); - ts.push(self.parse_ty(false)); + if self.token != token::RPAREN { + ts.push(self.parse_ty(false)); + } + else { + one_tuple = true; + } } - let t = if vec::len(ts) == 1u { ts[0].node } + let t = if ts.len() == 1 && !one_tuple { ts[0].node } else { ty_tup(ts) }; self.expect(token::RPAREN); t diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8f2ad6ecb90..ccb3947f834 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -414,6 +414,9 @@ pub fn print_type_ex(s: @ps, &&ty: @ast::Ty, print_colons: bool) { ast::ty_tup(elts) => { popen(s); commasep(s, inconsistent, elts, print_type); + if elts.len() == 1 { + word(s.s, ~","); + } pclose(s); } ast::ty_bare_fn(f) => { diff --git a/src/test/run-pass/one-tuple.rs b/src/test/run-pass/one-tuple.rs index 4f2daa7d608..9d01fbface0 100644 --- a/src/test/run-pass/one-tuple.rs +++ b/src/test/run-pass/one-tuple.rs @@ -16,5 +16,9 @@ fn main() { assert x == 'c'; } } + // test the 1-tuple type too + let x: (char,) = ('d',); + let (y,) = x; + assert y == 'd'; } diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index d6470ad72b0..3694ffdfde0 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -636,11 +636,12 @@ struct Triple { x: int, y: int, z: int } pub fn main() { unsafe { - let r = (1,2,3,true,false, Triple {x:5,y:4,z:3}); + let r = (1,2,3,true,false, Triple {x:5,y:4,z:3}, (12,)); let p = ptr::addr_of(&r) as *c_void; let u = my_visitor(@Stuff {mut ptr1: p, mut ptr2: p, - mut vals: ~[]}); + mut vals: ~[] + }); let v = ptr_visit_adaptor(Inner {inner: u}); let td = get_tydesc_for(r); unsafe { error!("tydesc sz: %u, align: %u", @@ -653,7 +654,7 @@ pub fn main() { } error!("%?", copy u.vals); assert u.vals == ~[ - ~"1", ~"2", ~"3", ~"true", ~"false", ~"5", ~"4", ~"3" + ~"1", ~"2", ~"3", ~"true", ~"false", ~"5", ~"4", ~"3", ~"12" ]; } } -- cgit 1.4.1-3-g733a5