diff options
| author | P1start <rewi-github@whanau.org> | 2014-08-10 15:54:33 +1200 |
|---|---|---|
| committer | P1start <rewi-github@whanau.org> | 2014-09-10 10:25:12 +1200 |
| commit | bf274bc18bcbfea1377c5c64ae0cc099b03d9beb (patch) | |
| tree | 78f4b0455b6c93991836bed81b7b57096737b462 /src/libsyntax | |
| parent | 651106462c357b71a4ca2c02ba2bfedfc38b0035 (diff) | |
| download | rust-bf274bc18bcbfea1377c5c64ae0cc099b03d9beb.tar.gz rust-bf274bc18bcbfea1377c5c64ae0cc099b03d9beb.zip | |
Implement tuple and tuple struct indexing
This allows code to access the fields of tuples and tuple structs:
let x = (1i, 2i);
assert_eq!(x.1, 2);
struct Point(int, int);
let origin = Point(0, 0);
assert_eq!(origin.0, 0);
assert_eq!(origin.1, 0);
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 42 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 6 |
6 files changed, 89 insertions, 1 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 68a1c521f19..4e65082fe3a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -540,6 +540,7 @@ pub enum Expr_ { ExprAssign(Gc<Expr>, Gc<Expr>), ExprAssignOp(BinOp, Gc<Expr>, Gc<Expr>), ExprField(Gc<Expr>, SpannedIdent, Vec<P<Ty>>), + ExprTupField(Gc<Expr>, Spanned<uint>, Vec<P<Ty>>), ExprIndex(Gc<Expr>, Gc<Expr>), /// Variable reference, possibly containing `::` and/or diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 64ab0e5cb19..6bd1fba4b58 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -120,6 +120,8 @@ pub trait AstBuilder { fn expr_mut_addr_of(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr>; fn expr_field_access(&self, span: Span, expr: Gc<ast::Expr>, ident: ast::Ident) -> Gc<ast::Expr>; + fn expr_tup_field_access(&self, sp: Span, expr: Gc<ast::Expr>, + idx: uint) -> Gc<ast::Expr>; fn expr_call(&self, span: Span, expr: Gc<ast::Expr>, args: Vec<Gc<ast::Expr>>) -> Gc<ast::Expr>; fn expr_call_ident(&self, span: Span, id: ast::Ident, @@ -605,6 +607,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let id = Spanned { node: ident, span: field_span }; self.expr(sp, ast::ExprField(expr, id, Vec::new())) } + fn expr_tup_field_access(&self, sp: Span, expr: Gc<ast::Expr>, idx: uint) -> Gc<ast::Expr> { + let field_span = Span { + lo: sp.lo - Pos::from_uint(idx.to_string().len()), + hi: sp.hi, + expn_info: sp.expn_info, + }; + + let id = Spanned { node: idx, span: field_span }; + self.expr(sp, ast::ExprTupField(expr, id, Vec::new())) + } fn expr_addr_of(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr> { self.expr(sp, ast::ExprAddrOf(ast::MutImmutable, e)) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 7deabed04b8..30b7317fa56 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -134,6 +134,10 @@ pub trait Folder { noop_fold_ident(i, self) } + fn fold_uint(&mut self, i: uint) -> uint { + noop_fold_uint(i, self) + } + fn fold_path(&mut self, p: &Path) -> Path { noop_fold_path(p, self) } @@ -466,6 +470,10 @@ pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident { i } +pub fn noop_fold_uint<T: Folder>(i: uint, _: &mut T) -> uint { + i +} + pub fn noop_fold_path<T: Folder>(p: &Path, fld: &mut T) -> Path { ast::Path { span: fld.new_span(p.span), @@ -1180,6 +1188,11 @@ pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> { respan(id.span, folder.fold_ident(id.node)), tys.iter().map(|&x| folder.fold_ty(x)).collect()) } + ExprTupField(el, id, ref tys) => { + ExprTupField(folder.fold_expr(el), + respan(id.span, folder.fold_uint(id.node)), + tys.iter().map(|&x| folder.fold_ty(x)).collect()) + } ExprIndex(el, er) => { ExprIndex(folder.fold_expr(el), folder.fold_expr(er)) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6aff1152f7e..718d75aad89 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -23,7 +23,7 @@ use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, Explicit use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; -use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex}; +use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIndex}; use ast::{ExprLit, ExprLoop, ExprMac}; use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn}; @@ -1937,6 +1937,11 @@ impl<'a> Parser<'a> { ExprField(expr, ident, tys) } + pub fn mk_tup_field(&mut self, expr: Gc<Expr>, idx: codemap::Spanned<uint>, + tys: Vec<P<Ty>>) -> ast::Expr_ { + ExprTupField(expr, idx, tys) + } + pub fn mk_assign_op(&mut self, binop: ast::BinOp, lhs: Gc<Expr>, rhs: Gc<Expr>) -> ast::Expr_ { ExprAssignOp(binop, lhs, rhs) @@ -2286,6 +2291,41 @@ impl<'a> Parser<'a> { } } } + token::LIT_INTEGER(n) => { + let index = n.as_str(); + let dot = self.last_span.hi; + hi = self.span.hi; + self.bump(); + let (_, tys) = if self.eat(&token::MOD_SEP) { + self.expect_lt(); + self.parse_generic_values_after_lt() + } else { + (Vec::new(), Vec::new()) + }; + + let num = from_str::<uint>(index); + match num { + Some(n) => { + let id = spanned(dot, hi, n); + let field = self.mk_tup_field(e, id, tys); + e = self.mk_expr(lo, hi, field); + } + None => { + let last_span = self.last_span; + self.span_err(last_span, "invalid tuple or tuple struct index"); + } + } + } + token::LIT_FLOAT(n) => { + self.bump(); + let last_span = self.last_span; + self.span_err(last_span, + format!("unexpected token: `{}`", n.as_str()).as_slice()); + self.span_note(last_span, + "try parenthesizing the first index; e.g., `(foo.0).1`"); + self.abort_if_errors(); + + } _ => self.unexpected() } continue; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index eaeb6aaab8a..a4dff45ad35 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1607,6 +1607,18 @@ impl<'a> State<'a> { try!(word(&mut self.s, ">")); } } + ast::ExprTupField(ref expr, id, ref tys) => { + try!(self.print_expr(&**expr)); + try!(word(&mut self.s, ".")); + try!(self.print_uint(id.node)); + if tys.len() > 0u { + try!(word(&mut self.s, "::<")); + try!(self.commasep( + Inconsistent, tys.as_slice(), + |s, ty| s.print_type_ref(ty))); + try!(word(&mut self.s, ">")); + } + } ast::ExprIndex(ref expr, ref index) => { try!(self.print_expr(&**expr)); try!(word(&mut self.s, "[")); @@ -1738,6 +1750,10 @@ impl<'a> State<'a> { self.ann.post(self, NodeIdent(&ident)) } + pub fn print_uint(&mut self, i: uint) -> IoResult<()> { + word(&mut self.s, i.to_string().as_slice()) + } + pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> { try!(word(&mut self.s, token::get_name(name).get())); self.ann.post(self, NodeName(&name)) diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 65e192e8437..50b42ea2c0f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -830,6 +830,12 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en visitor.visit_ty(&**typ, env.clone()) } } + ExprTupField(ref subexpression, _, ref types) => { + visitor.visit_expr(&**subexpression, env.clone()); + for typ in types.iter() { + visitor.visit_ty(&**typ, env.clone()) + } + } ExprIndex(ref main_expression, ref index_expression) => { visitor.visit_expr(&**main_expression, env.clone()); visitor.visit_expr(&**index_expression, env.clone()) |
