diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2012-11-02 13:33:51 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2012-11-05 13:17:02 -0800 |
| commit | be93b29d304b310ec56630f5313ccddf3ae470ea (patch) | |
| tree | 72c84b2fdbd5b82b9366162382461f0d2fa38b1f /src/libsyntax | |
| parent | 9aadfc3f4b5df00a7f8e9b362385118ae1dba73e (diff) | |
| download | rust-be93b29d304b310ec56630f5313ccddf3ae470ea.tar.gz rust-be93b29d304b310ec56630f5313ccddf3ae470ea.zip | |
rustc: Implement parsing and typechecking for "once fn"
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 21 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 39 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 36 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
6 files changed, 88 insertions, 20 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 21b0af9420f..8667f36c749 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1061,6 +1061,25 @@ enum region_ { #[auto_serialize] #[auto_deserialize] +enum Onceness { + Once, + Many +} + +impl Onceness : cmp::Eq { + pure fn eq(other: &Onceness) -> bool { + match (self, *other) { + (Once, Once) | (Many, Many) => true, + _ => false + } + } + pure fn ne(other: &Onceness) -> bool { + !self.eq(other) + } +} + +#[auto_serialize] +#[auto_deserialize] enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -1070,7 +1089,7 @@ enum ty_ { ty_ptr(mt), ty_rptr(@region, mt), ty_rec(~[ty_field]), - ty_fn(proto, purity, @~[ty_param_bound], fn_decl), + ty_fn(proto, purity, Onceness, @~[ty_param_bound], fn_decl), ty_tup(~[@Ty]), ty_path(@path, node_id), ty_fixed_length(@Ty, Option<uint>), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index a8b0f444514..7c8909668f5 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -524,10 +524,11 @@ fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ { ty_ptr(mt) => ty_ptr(fold_mt(mt, fld)), ty_rptr(region, mt) => ty_rptr(region, fold_mt(mt, fld)), ty_rec(fields) => ty_rec(vec::map(fields, |f| fold_field(*f, fld))), - ty_fn(proto, purity, bounds, decl) => - ty_fn(proto, purity, - @vec::map(*bounds, - |x| fold_ty_param_bound(*x, fld)), + ty_fn(proto, purity, onceness, bounds, decl) => + ty_fn(proto, + purity, + onceness, + @vec::map(*bounds, |x| fold_ty_param_bound(*x, fld)), fold_fn_decl(decl, fld)), ty_tup(tys) => ty_tup(vec::map(tys, |ty| fld.fold_ty(*ty))), ty_path(path, id) => ty_path(fld.fold_path(path), fld.new_id(id)), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6615bc75169..63545a69608 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -287,7 +287,7 @@ impl Parser { pure fn id_to_str(id: ident) -> @~str { self.sess.interner.get(id) } - fn parse_ty_fn(purity: ast::purity) -> ty_ { + fn parse_ty_fn(purity: ast::purity, onceness: ast::Onceness) -> ty_ { let proto, bounds; if self.eat_keyword(~"extern") { self.expect_keyword(~"fn"); @@ -298,7 +298,17 @@ impl Parser { proto = self.parse_fn_ty_proto(); bounds = self.parse_optional_ty_param_bounds(); }; - ty_fn(proto, purity, bounds, self.parse_ty_fn_decl()) + ty_fn(proto, purity, onceness, bounds, self.parse_ty_fn_decl()) + } + + fn parse_ty_fn_with_onceness(purity: ast::purity) -> ty_ { + let onceness = self.parse_optional_onceness(); + self.parse_ty_fn(purity, onceness) + } + + fn parse_ty_fn_with_purity_and_onceness() -> ty_ { + let purity = self.parse_optional_purity(); + self.parse_ty_fn_with_onceness(purity) } fn parse_ty_fn_decl() -> fn_decl { @@ -526,15 +536,18 @@ impl Parser { let region = self.parse_region_with_sep(); let mt = self.parse_mt(); ty_rptr(region, mt) + } else if self.eat_keyword(~"once") { + self.parse_ty_fn(ast::impure_fn, ast::Once) } else if self.eat_keyword(~"pure") { - self.parse_ty_fn(ast::pure_fn) + self.parse_ty_fn_with_onceness(ast::pure_fn) } else if self.eat_keyword(~"unsafe") { - self.parse_ty_fn(ast::unsafe_fn) + self.parse_ty_fn_with_onceness(ast::unsafe_fn) } else if self.is_keyword(~"fn") { - self.parse_ty_fn(ast::impure_fn) + self.parse_ty_fn_with_onceness(ast::impure_fn) } else if self.eat_keyword(~"extern") { self.expect_keyword(~"fn"); - ty_fn(proto_bare, ast::impure_fn, @~[], self.parse_ty_fn_decl()) + ty_fn(proto_bare, ast::impure_fn, ast::Many, @~[], + self.parse_ty_fn_decl()) } else if self.token == token::MOD_SEP || is_ident(self.token) { let path = self.parse_path_with_tps(colons_before_params); ty_path(path, self.get_id()) @@ -2275,6 +2288,20 @@ impl Parser { self.get_id()), span: self.last_span} } + fn parse_optional_purity() -> ast::purity { + if self.eat_keyword(~"pure") { + ast::pure_fn + } else if self.eat_keyword(~"unsafe") { + ast::unsafe_fn + } else { + ast::impure_fn + } + } + + fn parse_optional_onceness() -> ast::Onceness { + if self.eat_keyword(~"once") { ast::Once } else { ast::Many } + } + fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] { let mut bounds = ~[]; if self.eat(token::COLON) { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 53c1ce1c7f5..0d139b101d8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -427,6 +427,7 @@ fn strict_keyword_table() -> HashMap<~str, ()> { ~"if", ~"impl", ~"let", ~"log", ~"loop", ~"match", ~"mod", ~"move", ~"mut", + ~"once", ~"priv", ~"pub", ~"pure", ~"ref", ~"return", ~"struct", diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3836c21ff24..e0b9958bcb7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -394,8 +394,9 @@ fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) { commasep(s, inconsistent, elts, print_type); pclose(s); } - ast::ty_fn(proto, purity, bounds, d) => { - print_ty_fn(s, Some(proto), purity, bounds, d, None, None, None); + ast::ty_fn(proto, purity, onceness, bounds, d) => { + print_ty_fn(s, Some(proto), purity, onceness, bounds, d, None, None, + None); } ast::ty_path(path, _) => print_path(s, path, print_colons), ast::ty_fixed_length(t, v) => { @@ -804,7 +805,7 @@ fn print_ty_method(s: ps, m: ast::ty_method) { hardbreak_if_not_bol(s); maybe_print_comment(s, m.span.lo); print_outer_attributes(s, m.attrs); - print_ty_fn(s, None, m.purity, + print_ty_fn(s, None, m.purity, ast::Many, @~[], m.decl, Some(m.ident), Some(m.tps), Some(m.self_ty.node)); word(s.s, ~";"); @@ -1273,7 +1274,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) { cbox(s, indent_unit); // head-box, will be closed by print-block at start ibox(s, 0u); - word(s.s, fn_header_info_to_str(None, None, Some(proto), + word(s.s, fn_header_info_to_str(None, None, Some(proto), ast::Many, ast::inherited)); print_fn_args_and_ret(s, decl, *cap_clause, None); space(s.s); @@ -1606,12 +1607,15 @@ fn print_self_ty(s: ps, self_ty: ast::self_ty_) -> bool { return true; } -fn print_fn(s: ps, decl: ast::fn_decl, purity: Option<ast::purity>, +fn print_fn(s: ps, + decl: ast::fn_decl, + purity: Option<ast::purity>, name: ast::ident, typarams: ~[ast::ty_param], opt_self_ty: Option<ast::self_ty_>, vis: ast::visibility) { - head(s, fn_header_info_to_str(opt_self_ty, purity, None, vis)); + head(s, fn_header_info_to_str(opt_self_ty, purity, None, ast::Many, + vis)); print_ident(s, name); print_type_params(s, typarams); print_fn_args_and_ret(s, decl, ~[], opt_self_ty); @@ -1831,14 +1835,17 @@ fn print_arg(s: ps, input: ast::arg) { end(s); } -fn print_ty_fn(s: ps, opt_proto: Option<ast::proto>, purity: ast::purity, +fn print_ty_fn(s: ps, + opt_proto: Option<ast::proto>, + purity: ast::purity, + onceness: ast::Onceness, bounds: @~[ast::ty_param_bound], decl: ast::fn_decl, id: Option<ast::ident>, tps: Option<~[ast::ty_param]>, opt_self_ty: Option<ast::self_ty_>) { ibox(s, indent_unit); word(s.s, fn_header_info_to_str(opt_self_ty, Some(purity), opt_proto, - ast::inherited)); + onceness, ast::inherited)); print_bounds(s, bounds); match id { Some(id) => { word(s.s, ~" "); print_ident(s, id); } _ => () } match tps { Some(tps) => print_type_params(s, tps), _ => () } @@ -2062,6 +2069,7 @@ fn next_comment(s: ps) -> Option<comments::cmnt> { fn fn_header_info_to_str(opt_sty: Option<ast::self_ty_>, opt_purity: Option<ast::purity>, opt_p: Option<ast::proto>, + onceness: ast::Onceness, vis: ast::visibility) -> ~str { let mut s = visibility_qualified(vis, ~""); @@ -2082,6 +2090,11 @@ fn fn_header_info_to_str(opt_sty: Option<ast::self_ty_>, str::push_str(&mut s, opt_proto_to_str(opt_p)); + match onceness { + ast::Once => str::push_str(&mut s, ~"once "), + ast::Many => {} + } + return s; } @@ -2101,6 +2114,13 @@ pure fn purity_to_str(p: ast::purity) -> ~str { } } +pure fn onceness_to_str(o: ast::Onceness) -> ~str { + match o { + ast::Once => ~"once", + ast::Many => ~"many" + } +} + fn print_purity(s: ps, p: ast::purity) { match p { ast::impure_fn => (), diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 2dbe2b16044..be6fb4cefa8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -203,7 +203,7 @@ fn visit_ty<E>(t: @Ty, e: E, v: vt<E>) { ty_tup(ts) => for ts.each |tt| { v.visit_ty(*tt, e, v); }, - ty_fn(_, _, bounds, decl) => { + ty_fn(_, _, _, bounds, decl) => { for decl.inputs.each |a| { v.visit_ty(a.ty, e, v); } visit_ty_param_bounds(bounds, e, v); v.visit_ty(decl.output, e, v); |
