From 057617c6654bfd5a677112cd26141d0b9c137145 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 20 Dec 2011 16:33:55 +0100 Subject: [PATCH] Parse `iface` items and interface references in `impl` items. The (temporary) syntax is iface seq { fn len() -> uint; fn iter(f: block(T)); } // The 'blah' can be left of to default the name of the // impl to seq. The 'of seq' can be left off when // not implementing a named interface. impl blah of seq for [T] { fn len() -> uint { vec::len(self) } fn iter(f: block(T)) { for x in self { f(x); } } } --- src/comp/metadata/encoder.rs | 15 ++- src/comp/middle/ast_map.rs | 2 +- src/comp/middle/resolve.rs | 28 ++--- src/comp/middle/trans.rs | 4 +- src/comp/middle/tstate/pre_post_conditions.rs | 5 +- src/comp/middle/ty.rs | 91 ++++++++------ src/comp/middle/typeck.rs | 18 ++- src/comp/syntax/ast.rs | 4 +- src/comp/syntax/fold.rs | 15 ++- src/comp/syntax/parse/parser.rs | 117 +++++++++--------- src/comp/syntax/print/pprust.rs | 38 ++++-- src/comp/syntax/visit.rs | 11 +- 12 files changed, 209 insertions(+), 139 deletions(-) diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index ba87bcf9dab..6bbca1335a1 100644 --- a/src/comp/metadata/encoder.rs +++ b/src/comp/metadata/encoder.rs @@ -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]) { + // 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] */ } } } diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs index f1ecfb29e2a..0b0d0337d2d 100644 --- a/src/comp/middle/ast_map.rs +++ b/src/comp/middle/ast_map.rs @@ -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) { diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 393c7000bce..68d4d5aac30 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -401,8 +401,9 @@ fn resolve_names(e: @env, c: @ast::crate) { fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt) { 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 { 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 { _ { } } } - 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, ck_exports: option::t) { 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), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 366e515b05c..72c38582760 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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], diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 83acaaa5902..8f960eea6c0 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -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); } } } } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 2b18b1de08c..f668184acb6 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -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::(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) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 362f01b7573..21adb2af201 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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); 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 { "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(i: @item, e: E, v: vt) { 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); + } + } } }