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); } }
    }
This commit is contained in:
Marijn Haverbeke 2011-12-20 16:33:55 +01:00
parent 9292744959
commit 057617c665
12 changed files with 209 additions and 139 deletions

View File

@ -64,6 +64,7 @@ fn encode_native_module_item_paths(ebml_w: ebml::writer, nmod: native_mod,
fn encode_module_item_paths(ebml_w: ebml::writer, module: _mod, path: [str],
&index: [entry<str>]) {
// FIXME factor out add_to_index/start/encode_name/encode_def_id/end ops
for it: @item in module.items {
if !ast_util::is_exported(it.ident, module) { cont; }
alt it.node {
@ -137,7 +138,14 @@ fn encode_module_item_paths(ebml_w: ebml::writer, module: _mod, path: [str],
encode_def_id(ebml_w, local_def(it.id));
ebml::end_tag(ebml_w);
}
item_impl(_, _, _) {}
item_iface(_, _) {
add_to_index(ebml_w, path, index, it.ident);
ebml::start_tag(ebml_w, tag_paths_data_item);
encode_name(ebml_w, it.ident);
encode_def_id(ebml_w, local_def(it.id));
ebml::end_tag(ebml_w);
}
item_impl(_, _, _, _) {}
}
}
}
@ -252,7 +260,7 @@ fn encode_info_for_mod(ebml_w: ebml::writer, md: _mod,
encode_name(ebml_w, name);
for i in md.items {
alt i.node {
item_impl(_, _, _) {
item_impl(_, _, _, _) {
if ast_util::is_exported(i.ident, md) {
ebml::start_tag(ebml_w, tag_mod_impl);
ebml_w.writer.write(str::bytes(def_to_str(local_def(i.id))));
@ -363,7 +371,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_symbol(ecx, ebml_w, ctor_id);
ebml::end_tag(ebml_w);
}
item_impl(tps, _, methods) {
item_impl(tps, _, _, methods) {
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'i' as u8);
@ -390,6 +398,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::end_tag(ebml_w);
}
}
item_iface(_, _) { /* FIXME[impl] */ }
}
}

View File

@ -71,7 +71,7 @@ fn map_item(cx: ctx, i: @item) {
cx.map.insert(m.id, node_obj_method(m));
}
}
item_impl(_, _, ms) {
item_impl(_, _, _, ms) {
for m in ms { cx.map.insert(m.id, node_method(m)); }
}
item_res(_, _, _, dtor_id, ctor_id) {

View File

@ -401,8 +401,9 @@ fn resolve_names(e: @env, c: @ast::crate) {
fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt<scopes>) {
let sc = cons(scope_item(i), @sc);
alt i.node {
ast::item_impl(tps, sty, methods) {
visit::visit_ty(sty, sc, v);
ast::item_impl(tps, ifce, sty, methods) {
alt ifce { some(ty) { v.visit_ty(ty, sc, v); } _ {} }
v.visit_ty(sty, sc, v);
for m in methods {
v.visit_fn_proto(m.decl, tps + m.tps, m.body, m.span,
some(m.ident), m.id, sc, v);
@ -802,14 +803,15 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
ast::item_obj(ob, ty_params, _) {
ret lookup_in_obj(name, ob, ty_params, ns, it.id);
}
ast::item_impl(ty_params, _, _) {
ast::item_impl(ty_params, _, _, _) {
if (name == "self" && ns == ns_value) {
ret some(ast::def_self(local_def(it.id)));
}
if ns == ns_type { ret lookup_in_ty_params(name, ty_params); }
}
ast::item_tag(_, ty_params) {
if ns == ns_type { ret lookup_in_ty_params(name, ty_params); }
ast::item_iface(tps, _) | ast::item_tag(_, tps) |
ast::item_ty(_, tps) {
if ns == ns_type { ret lookup_in_ty_params(name, tps); }
}
ast::item_mod(_) {
ret lookup_in_local_mod(e, it.id, sp, name, ns, inside);
@ -817,9 +819,6 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
ast::item_native_mod(m) {
ret lookup_in_local_native_mod(e, it.id, sp, name, ns);
}
ast::item_ty(_, ty_params) {
if ns == ns_type { ret lookup_in_ty_params(name, ty_params); }
}
_ { }
}
}
@ -1064,7 +1063,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option::t<def> {
ast::item_native_mod(_) {
if ns == ns_module { ret some(ast::def_native_mod(local_def(i.id))); }
}
ast::item_ty(_, _) {
ast::item_ty(_, _) | item_iface(_, _) | item_tag(_, _) {
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); }
}
ast::item_res(_, _, _, _, ctor_id) {
@ -1076,9 +1075,6 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option::t<def> {
_ { }
}
}
ast::item_tag(_, _) {
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); }
}
ast::item_obj(_, _, ctor_id) {
alt ns {
ns_value. {
@ -1322,7 +1318,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) |
ast::item_native_mod(_) | ast::item_ty(_, _) |
ast::item_res(_, _, _, _, _) | ast::item_obj(_, _, _) |
ast::item_impl(_, _, _) {
ast::item_impl(_, _, _, _) | ast::item_iface(_, _) {
add_to_index(index, it.ident, mie_item(it));
}
ast::item_tag(variants, _) {
@ -1570,7 +1566,9 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
ast::item_const(_, _) | ast::item_fn(_, _, _) {
add_name(values, it.span, it.ident);
}
ast::item_ty(_, _) { add_name(types, it.span, it.ident); }
ast::item_ty(_, _) | ast::item_iface(_, _) {
add_name(types, it.span, it.ident);
}
ast::item_res(_, _, _, _, _) | ast::item_obj(_, _, _) {
add_name(types, it.span, it.ident);
add_name(values, it.span, it.ident);
@ -1768,7 +1766,7 @@ fn find_impls_in_item(i: @ast::item, &impls: [@_impl],
name: option::t<ident>,
ck_exports: option::t<ast::_mod>) {
alt i.node {
ast::item_impl(_, _, mthds) {
ast::item_impl(_, _, _, mthds) {
if alt name { some(n) { n == i.ident } _ { true } } &&
alt ck_exports { some(m) { is_exported(i.ident, m) } _ { true } } {
impls += [@{did: local_def(i.id),

View File

@ -5013,7 +5013,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
with *extend_path(cx, item.ident)};
trans_obj(sub_cx, item.span, ob, ctor_id, tps);
}
ast::item_impl(tps, _, ms) {
ast::item_impl(tps, _, _, ms) {
trans_impl(cx, item.ident, ms, item.id, tps);
}
ast::item_res(decl, tps, body, dtor_id, ctor_id) {
@ -5340,7 +5340,7 @@ fn collect_item_2(ccx: @crate_ctxt, i: @ast::item, &&pt: [str],
ccx.obj_methods.insert(m.id, ());
}
}
ast::item_impl(tps, _, methods) {
ast::item_impl(tps, _, _, methods) {
let name = ccx.names.next(i.ident);
for m in methods {
register_fn(ccx, i.span, pt + [name, m.ident],

View File

@ -64,8 +64,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
}
item_mod(m) { find_pre_post_mod(m); }
item_native_mod(nm) { find_pre_post_native_mod(nm); }
item_ty(_, _) { ret; }
item_tag(_, _) { ret; }
item_ty(_, _) | item_tag(_, _) | item_iface(_, _) { ret; }
item_res(_, _, body, dtor_id, _) {
let fcx =
{enclosing: ccx.fm.get(dtor_id),
@ -75,7 +74,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
find_pre_post_fn(fcx, body);
}
item_obj(o, _, _) {for m in o.methods { find_pre_post_method(ccx, m); }}
item_impl(_, _, ms) { for m in ms { find_pre_post_method(ccx, m); } }
item_impl(_, _, _, ms) { for m in ms { find_pre_post_method(ccx, m); } }
}
}

View File

@ -73,6 +73,7 @@ export mk_native;
export mk_native_fn;
export mk_nil;
export mk_obj;
export mk_iface;
export mk_res;
export mk_param;
export mk_ptr;
@ -123,6 +124,7 @@ export ty_vec;
export ty_native;
export ty_nil;
export ty_obj;
export ty_iface;
export ty_res;
export ty_param;
export ty_ptr;
@ -256,6 +258,7 @@ tag sty {
ty_fn(fn_ty);
ty_native_fn([arg], t);
ty_obj([method]);
ty_iface(def_id, [t]);
ty_res(def_id, t, [t]);
ty_tup([t]);
ty_var(int); // type variable
@ -444,7 +447,7 @@ fn mk_raw_ty(cx: ctxt, st: sty) -> @raw_t {
}
ty_param(_, _) { has_params = true; }
ty_var(_) { has_vars = true; }
ty_tag(_, tys) {
ty_tag(_, tys) | ty_iface(_, tys) {
for tt: t in tys { derive_flags_t(cx, has_params, has_vars, tt); }
}
ty_box(m) { derive_flags_mt(cx, has_params, has_vars, m); }
@ -584,6 +587,10 @@ fn mk_native_fn(cx: ctxt, args: [arg], ty: t) -> t {
fn mk_obj(cx: ctxt, meths: [method]) -> t { ret gen_ty(cx, ty_obj(meths)); }
fn mk_iface(cx: ctxt, did: ast::def_id, tys: [t]) -> t {
ret gen_ty(cx, ty_iface(did, tys));
}
fn mk_res(cx: ctxt, did: ast::def_id, inner: t, tps: [t]) -> t {
ret gen_ty(cx, ty_res(did, inner, tps));
}
@ -634,7 +641,7 @@ fn walk_ty(cx: ctxt, walker: ty_walk, ty: t) {
/* no-op */
}
ty_box(tm) | ty_vec(tm) | ty_ptr(tm) { walk_ty(cx, walker, tm.ty); }
ty_tag(tid, subtys) {
ty_tag(_, subtys) | ty_iface(_, subtys) {
for subty: t in subtys { walk_ty(cx, walker, subty); }
}
ty_rec(fields) {
@ -703,9 +710,10 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
ty = mk_vec(cx, {ty: fold_ty(cx, fld, tm.ty), mut: tm.mut});
}
ty_tag(tid, subtys) {
let new_subtys: [t] = [];
for subty: t in subtys { new_subtys += [fold_ty(cx, fld, subty)]; }
ty = mk_tag(cx, tid, new_subtys);
ty = mk_tag(cx, tid, vec::map(subtys, {|t| fold_ty(cx, fld, t) }));
}
ty_iface(did, subtys) {
ty = mk_iface(cx, did, vec::map(subtys, {|t| fold_ty(cx, fld, t) }));
}
ty_rec(fields) {
let new_fields: [field] = [];
@ -785,14 +793,10 @@ fn type_is_bool(cx: ctxt, ty: t) -> bool {
fn type_is_structural(cx: ctxt, ty: t) -> bool {
alt struct(cx, ty) {
ty_rec(_) { ret true; }
ty_tup(_) { ret true; }
ty_tag(_, _) { ret true; }
ty_fn(_) { ret true; }
ty_native_fn(_, _) { ret true; }
ty_obj(_) { ret true; }
ty_res(_, _, _) { ret true; }
_ { ret false; }
ty_rec(_) | ty_tup(_) | ty_tag(_, _) | ty_fn(_) |
ty_native_fn(_, _) | ty_obj(_) | ty_res(_, _, _) |
ty_iface(_, _) { true }
_ { false }
}
}
@ -973,7 +977,7 @@ fn type_kind(cx: ctxt, ty: t) -> ast::kind {
ty_opaque_closure. { kind_noncopyable }
// Those with refcounts-to-inner raise pinned to shared,
// lower unique to shared. Therefore just set result to shared.
ty_box(mt) { ast::kind_copyable }
ty_box(_) | ty_iface(_, _) { ast::kind_copyable }
// Boxes and unique pointers raise pinned to shared.
ty_vec(tm) | ty_uniq(tm) { type_kind(cx, tm.ty) }
// Records lower to the lowest of their members.
@ -1142,9 +1146,7 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
ty_send_type. | ty_type. | ty_native(_) | ty_ptr(_) { result = true; }
// Boxed types
ty_str. | ty_box(_) | ty_uniq(_) | ty_vec(_) | ty_fn(_) |
ty_native_fn(_, _) | ty_obj(_) {
result = false;
}
ty_native_fn(_, _) | ty_obj(_) | ty_iface(_, _) { result = false; }
// Structural types
ty_tag(did, tps) {
let variants = tag_variants(cx, did);
@ -1332,6 +1334,11 @@ fn hash_type_structure(st: sty) -> uint {
ty_send_type. { ret 38u; }
ty_opaque_closure. { ret 39u; }
ty_named(t, name) { (str::hash(*name) << 5u) + hash_subty(40u, t) }
ty_iface(did, tys) {
let h = hash_def(41u, did);
for typ: t in tys { h += (h << 5u) + typ; }
ret h;
}
}
}
@ -2024,6 +2031,20 @@ mod unify {
}
}
fn unify_tps(cx: @ctxt, expected_tps: [t], actual_tps: [t],
variance: variance, finish: block([t]) -> result) -> result {
let result_tps = [], i = 0u;
for exp in expected_tps {
let act = actual_tps[i];
i += 1u;
let result = unify_step(cx, exp, act, variance);
alt result {
ures_ok(rty) { result_tps += [rty]; }
_ { ret result; }
}
}
finish(result_tps)
}
fn unify_step(cx: @ctxt, expected: t, actual: t,
variance: variance) -> result {
// FIXME: rewrite this using tuple pattern matching when available, to
@ -2109,31 +2130,31 @@ mod unify {
ty::ty_tag(expected_id, expected_tps) {
alt struct(cx.tcx, actual) {
ty::ty_tag(actual_id, actual_tps) {
if expected_id.crate != actual_id.crate ||
expected_id.node != actual_id.node {
if expected_id != actual_id {
ret ures_err(terr_mismatch);
}
// TODO: factor this cruft out
let result_tps: [t] = [];
let i = 0u;
let expected_len = vec::len::<t>(expected_tps);
while i < expected_len {
let expected_tp = expected_tps[i];
let actual_tp = actual_tps[i];
let result = unify_step(
cx, expected_tp, actual_tp, variance);
alt result {
ures_ok(rty) { result_tps += [rty]; }
_ { ret result; }
}
i += 1u;
}
ret ures_ok(mk_tag(cx.tcx, expected_id, result_tps));
ret unify_tps(cx, expected_tps, actual_tps, variance, {|tps|
ures_ok(mk_tag(cx.tcx, expected_id, tps))
});
}
_ {/* fall through */ }
}
ret ures_err(terr_mismatch);
}
ty_iface(expected_id, expected_tps) {
alt struct(cx.tcx, actual) {
ty::ty_iface(actual_id, actual_tps) {
if expected_id != actual_id {
ret ures_err(terr_mismatch);
}
ret unify_tps(cx, expected_tps, actual_tps, variance, {|tps|
ures_ok(mk_iface(cx.tcx, expected_id, tps))
});
}
_ {}
}
ret ures_err(terr_mismatch);
}
ty::ty_box(expected_mt) {
alt struct(cx.tcx, actual) {
ty::ty_box(actual_mt) {

View File

@ -422,7 +422,15 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_impl(_, _, _) | ast::item_mod(_) |
ast::item_iface(tps, methods) {
let t = ty::mk_named(tcx, ty::mk_iface(tcx, local_def(it.id),
mk_ty_params(tcx, tps)),
@it.ident);
let tpt = {kinds: ty_param_kinds(tps), ty: t};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_impl(_, _, _, _) | ast::item_mod(_) |
ast::item_native_mod(_) { fail; }
}
}
@ -647,7 +655,7 @@ mod collect {
write::ty_only(cx.tcx, it.id, tpt.ty);
get_tag_variant_types(cx, tpt.ty, variants, ty_params);
}
ast::item_impl(_, selfty, ms) {
ast::item_impl(_, _, selfty, ms) {
for m in ms {
let ty = ty::mk_fn(cx.tcx, ty_of_fn_decl(cx.tcx, m_collect,
m.decl));
@ -1429,9 +1437,9 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
some(m) {
let (n_tps, self_ty) = if did.crate == ast::local_crate {
alt fcx.ccx.tcx.items.get(did.node) {
ast_map::node_item(@{node: ast::item_impl(tps, st, _),
ast_map::node_item(@{node: ast::item_impl(ts, _, st, _),
_}) {
(vec::len(tps), ast_ty_to_ty_crate(fcx.ccx, st))
(vec::len(ts), ast_ty_to_ty_crate(fcx.ccx, st))
}
}
} else {
@ -2637,7 +2645,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
// Now remove the info from the stack.
vec::pop(ccx.self_infos);
}
ast::item_impl(_, ty, ms) {
ast::item_impl(_, _, ty, ms) {
ccx.self_infos += [self_impl(ast_ty_to_ty(ccx.tcx, m_check, ty))];
for m in ms { check_method(ccx, m); }
vec::pop(ccx.self_infos);

View File

@ -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 =

View File

@ -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 {

View File

@ -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") {

View File

@ -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 {

View File

@ -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);
}
}
}
}