diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-12-20 16:33:55 +0100 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-12-23 18:09:25 +0100 |
| commit | 057617c6654bfd5a677112cd26141d0b9c137145 (patch) | |
| tree | 316c1b2cbcb11aa3cd02f05107e76fa5cd624fef /src/comp/syntax | |
| parent | 92927449595782926c4db5a579ba7e4c6952287d (diff) | |
Parse `iface` items and interface references in `impl` items.
The (temporary) syntax is
iface seq<T> {
fn len() -> uint;
fn iter(f: block(T));
}
// The 'blah<T>' can be left of to default the name of the
// impl to seq<T>. The 'of seq<T>' can be left off when
// not implementing a named interface.
impl blah<T> of seq<T> for [T] {
fn len() -> uint { vec::len(self) }
fn iter(f: block(T)) { for x in self { f(x); } }
}
Diffstat (limited to 'src/comp/syntax')
| -rw-r--r-- | src/comp/syntax/ast.rs | 4 | ||||
| -rw-r--r-- | src/comp/syntax/fold.rs | 15 | ||||
| -rw-r--r-- | src/comp/syntax/parse/parser.rs | 117 | ||||
| -rw-r--r-- | src/comp/syntax/print/pprust.rs | 38 | ||||
| -rw-r--r-- | src/comp/syntax/visit.rs | 11 |
5 files changed, 110 insertions, 75 deletions
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index a94e860b764..9952dd55546 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -490,7 +490,9 @@ tag item_ { item_obj(_obj, [ty_param], /* constructor id */node_id); item_res(fn_decl /* dtor */, [ty_param], blk, node_id /* dtor id */, node_id /* ctor id */); - item_impl([ty_param], @ty /* self */, [@method]); + item_iface([ty_param], [ty_method]); + item_impl([ty_param], option::t<@ty> /* iface */, + @ty /* self */, [@method]); } type native_item = diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 0c136819ce9..d06c98b0a31 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -65,7 +65,7 @@ type a_f = fold_native_mod: fn@(native_mod) -> native_mod, fold_variant: fn@(variant) -> variant, fold_ident: fn@(&&ident) -> ident, - fold_path: fn@(@path) -> @path, + fold_path: fn@(&&@path) -> @path, fold_local: fn@(&&@local) -> @local, map_exprs: fn@(fn@(&&@expr) -> @expr, [@expr]) -> [@expr], new_id: fn@(node_id) -> node_id, @@ -94,7 +94,7 @@ fn nf_mod_dummy(_m: _mod) -> _mod { fail; } fn nf_native_mod_dummy(_n: native_mod) -> native_mod { fail; } fn nf_variant_dummy(_v: variant) -> variant { fail; } fn nf_ident_dummy(&&_i: ident) -> ident { fail; } -fn nf_path_dummy(_p: @path) -> @path { fail; } +fn nf_path_dummy(&&_p: @path) -> @path { fail; } fn nf_obj_field_dummy(_o: obj_field) -> obj_field { fail; } fn nf_local_dummy(&&_o: @local) -> @local { fail; } @@ -243,10 +243,13 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { methods: vec::map(o.methods, fld.fold_method)}, typms, d) } - item_impl(tps, ty, methods) { - item_impl(tps, fld.fold_ty(ty), + item_impl(tps, ifce, ty, methods) { + item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty), vec::map(methods, fld.fold_method)) } + item_iface(tps, methods) { + item_iface(tps, methods) + } item_res(decl, typms, body, did, cid) { item_res(fold_fn_decl(decl, fld), typms, fld.fold_block(body), did, cid) @@ -471,7 +474,7 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { fn noop_fold_ident(&&i: ident, _fld: ast_fold) -> ident { ret i; } -fn noop_fold_path(p: path_, fld: ast_fold) -> path_ { +fn noop_fold_path(&&p: path_, fld: ast_fold) -> path_ { ret {global: p.global, idents: vec::map(p.idents, fld.fold_ident), types: vec::map(p.types, fld.fold_ty)}; @@ -630,7 +633,7 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold { fn f_ident(afp: ast_fold_precursor, f: ast_fold, &&x: ident) -> ident { ret afp.fold_ident(x, f); } - fn f_path(afp: ast_fold_precursor, f: ast_fold, x: @path) -> @path { + fn f_path(afp: ast_fold_precursor, f: ast_fold, &&x: @path) -> @path { ret @{node: afp.fold_path(x.node, f), span: afp.new_span(x.span)}; } fn f_local(afp: ast_fold_precursor, f: ast_fold, &&x: @local) -> @local { diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 484659f4bc5..8299f23ae20 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -165,7 +165,7 @@ fn bad_expr_word_table() -> hashmap<str, ()> { "cont", "ret", "be", "fail", "type", "resource", "check", "assert", "claim", "native", "fn", "lambda", "pure", "unsafe", "block", "import", "export", "let", "const", - "log", "tag", "obj", "copy", "sendfn", "impl"] { + "log", "tag", "obj", "copy", "sendfn", "impl", "iface"] { words.insert(word, ()); } words @@ -285,7 +285,7 @@ fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ { constraints: constrs}); } -fn parse_ty_obj(p: parser) -> ast::ty_ { +fn parse_ty_methods(p: parser) -> [ast::ty_method] { fn parse_method_sig(p: parser) -> ast::ty_method { let flo = p.get_lo_pos(); let proto: ast::proto = parse_method_proto(p); @@ -298,10 +298,8 @@ fn parse_ty_obj(p: parser) -> ast::ty_ { } } } - let meths = - parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), - parse_method_sig, p); - ret ast::ty_obj(meths.node); + parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), + parse_method_sig, p).node } fn parse_mt(p: parser) -> ast::mt { @@ -519,7 +517,7 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty { } else if eat_word(p, "sendfn") { t = parse_ty_fn(ast::proto_send, p); } else if eat_word(p, "obj") { - t = parse_ty_obj(p); + t = ast::ty_obj(parse_ty_methods(p)); } else if p.peek() == token::MOD_SEP || is_ident(p.peek()) { let path = parse_path(p); t = ast::ty_path(path, p.get_id()); @@ -676,47 +674,22 @@ fn is_plain_ident(p: parser) -> bool { fn parse_path(p: parser) -> @ast::path { let lo = p.get_lo_pos(); - let hi = lo; - - let global; - if p.peek() == token::MOD_SEP { - global = true; - p.bump(); - } else { global = false; } - - let ids: [ast::ident] = []; - while true { - alt p.peek() { - token::IDENT(i, _) { - hi = p.get_hi_pos(); - ids += [p.get_str(i)]; - hi = p.get_hi_pos(); - p.bump(); - if p.peek() == token::MOD_SEP && p.look_ahead(1u) != token::LT { - p.bump(); - } else { break; } - } - _ { break; } - } + let global = eat(p, token::MOD_SEP), ids = [parse_ident(p)]; + while p.look_ahead(1u) != token::LT && eat(p, token::MOD_SEP) { + ids += [parse_ident(p)]; } - ret @spanned(lo, hi, {global: global, idents: ids, types: []}); + ret @spanned(lo, p.get_last_hi_pos(), + {global: global, idents: ids, types: []}); } -fn parse_path_and_ty_param_substs(p: parser) -> @ast::path { +fn parse_path_and_ty_param_substs(p: parser, colons: bool) -> @ast::path { let lo = p.get_lo_pos(); let path = parse_path(p); - if p.peek() == token::MOD_SEP { - p.bump(); - - let seq = - parse_seq_lt_gt(some(token::COMMA), {|p| parse_ty(p, false)}, p); - let hi = seq.span.hi; - path = @spanned(lo, hi, - {global: path.node.global, - idents: path.node.idents, - types: seq.node}); - } - ret path; + if colons ? eat(p, token::MOD_SEP) : p.peek() == token::LT { + let seq = parse_seq_lt_gt(some(token::COMMA), + {|p| parse_ty(p, false)}, p); + @spanned(lo, seq.span.hi, {types: seq.node with path.node}) + } else { path } } fn parse_mutability(p: parser) -> ast::mutability { @@ -958,7 +931,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { is_ident(p.peek()) && !is_word(p, "true") && !is_word(p, "false") { check_bad_word(p); - let pth = parse_path_and_ty_param_substs(p); + let pth = parse_path_and_ty_param_substs(p, true); hi = pth.span.hi; ex = ast::expr_path(pth); } else { @@ -984,10 +957,11 @@ fn parse_syntax_ext(p: parser) -> @ast::expr { } fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr { - let pth = parse_path(p); - if vec::len(pth.node.idents) == 0u { - p.fatal("expected a syntax expander name"); + alt p.peek() { + token::IDENT(_, _) {} + _ { p.fatal("expected a syntax expander name"); } } + let pth = parse_path(p); //temporary for a backwards-compatible cycle: let sep = seq_sep(token::COMMA); let es = @@ -1518,7 +1492,7 @@ fn parse_pat(p: parser) -> @ast::pat { let sub = eat(p, token::AT) ? some(parse_pat(p)) : none; pat = ast::pat_bind(name, sub); } else { - let tag_path = parse_path_and_ty_param_substs(p); + let tag_path = parse_path_and_ty_param_substs(p, true); hi = tag_path.span.hi; let args: [@ast::pat]; alt p.peek() { @@ -1751,12 +1725,9 @@ fn parse_ty_param(p: parser) -> ast::ty_param { } fn parse_ty_params(p: parser) -> [ast::ty_param] { - let ty_params: [ast::ty_param] = []; - if p.peek() == token::LT { - p.bump(); - ty_params = parse_seq_to_gt(some(token::COMMA), parse_ty_param, p); - } - ret ty_params; + if eat(p, token::LT) { + parse_seq_to_gt(some(token::COMMA), parse_ty_param, p) + } else { [] } } fn parse_fn_decl(p: parser, proto: ast::proto, purity: ast::purity) @@ -1866,15 +1837,47 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item { attrs); } -fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item { +fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item { let lo = p.get_last_lo_pos(), ident = parse_ident(p), + tps = parse_ty_params(p), meths = parse_ty_methods(p); + ret mk_item(p, lo, p.get_last_hi_pos(), ident, + ast::item_iface(tps, meths), attrs); +} + +fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item { + let lo = p.get_last_lo_pos(), ident, tps, ifce; + fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty { + @{node: ast::ty_path(pt, p.get_id()), span: pt.span} + } + if eat_word(p, "of") { + let path = parse_path_and_ty_param_substs(p, false); + tps = vec::map(path.node.types, {|tp| + alt tp.node { + ast::ty_path(pt, _) { + if vec::len(pt.node.idents) == 1u && + vec::len(pt.node.types) == 0u { + ret {ident: pt.node.idents[0], kind: ast::kind_sendable}; + } + } + _ {} + } + p.fatal("only single-word, parameter-less types allowed here"); + }); + ident = path.node.idents[vec::len(path.node.idents)-1u]; + ifce = some(wrap_path(p, path)); + } else { + ident = parse_ident(p); tps = parse_ty_params(p); + ifce = if eat_word(p, "of") { + some(wrap_path(p, parse_path_and_ty_param_substs(p, false))) + } else { none }; + }; expect_word(p, "for"); let ty = parse_ty(p, false), meths = []; expect(p, token::LBRACE); while !eat(p, token::RBRACE) { meths += [parse_method(p, true)]; } ret mk_item(p, lo, p.get_last_hi_pos(), ident, - ast::item_impl(tps, ty, meths), attrs); + ast::item_impl(tps, ifce, ty, meths), attrs); } fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item { @@ -2145,6 +2148,8 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> { } else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN { p.bump(); ret some(parse_item_obj(p, attrs)); + } else if eat_word(p, "iface") { + ret some(parse_item_iface(p, attrs)); } else if eat_word(p, "impl") { ret some(parse_item_impl(p, attrs)); } else if eat_word(p, "resource") { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index e2856c60f8d..99793d1b816 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -311,14 +311,7 @@ fn print_type(s: ps, &&ty: @ast::ty) { ast::ty_obj(methods) { head(s, "obj"); bopen(s); - for m: ast::ty_method in methods { - hardbreak_if_not_bol(s); - cbox(s, indent_unit); - maybe_print_comment(s, m.span.lo); - print_ty_fn(s, m.decl, some(m.ident)); - word(s.s, ";"); - end(s); - } + for m in methods { print_ty_method(s, m); } bclose(s, ty.span); } ast::ty_path(path, _) { print_path(s, path, false); } @@ -473,11 +466,19 @@ fn print_item(s: ps, &&item: @ast::item) { } bclose(s, item.span); } - ast::item_impl(tps, ty, methods) { + ast::item_impl(tps, ifce, ty, methods) { head(s, "impl"); word(s.s, item.ident); print_type_params(s, tps); - nbsp(s); + space(s.s); + alt ifce { + some(ty) { + word_nbsp(s, "of"); + print_type(s, ty); + space(s.s); + } + _ {} + } word_nbsp(s, "for"); print_type(s, ty); space(s.s); @@ -491,6 +492,14 @@ fn print_item(s: ps, &&item: @ast::item) { } bclose(s, item.span); } + ast::item_iface(tps, methods) { + head(s, "iface"); + word(s.s, item.ident); + print_type_params(s, tps); + bopen(s); + for meth in methods { print_ty_method(s, meth); } + bclose(s, item.span); + } ast::item_res(decl, tps, body, dt_id, ct_id) { head(s, "resource"); word(s.s, item.ident); @@ -506,6 +515,15 @@ fn print_item(s: ps, &&item: @ast::item) { s.ann.post(ann_node); } +fn print_ty_method(s: ps, m: ast::ty_method) { + hardbreak_if_not_bol(s); + cbox(s, indent_unit); + maybe_print_comment(s, m.span.lo); + print_ty_fn(s, m.decl, some(m.ident)); + word(s.s, ";"); + end(s); +} + fn print_outer_attributes(s: ps, attrs: [ast::attribute]) { let count = 0; for attr: ast::attribute in attrs { diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index dc91064dba6..ecdf8c9a05d 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -120,13 +120,20 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { some(m.ident), m.id, e, v); } } - item_impl(_, ty, methods) { - visit_ty(ty, e, v); + item_impl(_, ifce, ty, methods) { + alt ifce { some(ty) { v.visit_ty(ty, e, v); } _ {} } + v.visit_ty(ty, e, v); for m in methods { v.visit_fn_proto(m.decl, m.tps, m.body, m.span, some(m.ident), m.id, e, v); } } + item_iface(_, methods) { + for m in methods { + for a in m.decl.inputs { v.visit_ty(a.ty, e, v); } + v.visit_ty(m.decl.output, e, v); + } + } } } |
