}
},
- visit_class_item: fn@(_s: span, _p: ast::privacy,
- c: ast::class_member) {
- alt c {
- ast::instance_var(_, _, _, id) {
+ visit_class_item: fn@(c: @ast::class_member) {
+ alt c.node {
+ ast::instance_var(_, _, _, id,_) {
vfn(id)
}
ast::class_method(_) {
'u' { ast::unsafe_fn }
'f' { ast::impure_fn }
'p' { ast::pure_fn }
- }}];
+ }, privacy: ast::pub}];
}
@result
}
}
fn encode_class_item_paths(ebml_w: ebml::writer,
- items: [@class_item], path: [str], &index: [entry<str>]) {
+ items: [@class_member], path: [str], &index: [entry<str>]) {
for it in items {
- alt it.node.privacy {
+ alt ast_util::class_member_privacy(it) {
priv { cont; }
pub {
- let (id, ident) = alt it.node.decl {
- instance_var(v, _, _, vid) { (vid, v) }
+ let (id, ident) = alt it.node {
+ instance_var(v, _, _, vid, _) { (vid, v) }
class_method(it) { (it.id, it.ident) }
};
add_to_index(ebml_w, path, index, ident);
/* Returns an index of items in this class */
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
id: node_id, path: ast_map::path,
- items: [@class_item],
+ items: [@class_member],
global_index: @mut[entry<int>])
-> [entry<int>] {
let index = @mut [];
for ci in items {
/* We encode both private and public fields -- need to include
private fields to get the offsets right */
- alt ci.node.decl {
- instance_var(nm, _, mt, id) {
+ alt ci.node {
+ instance_var(nm, _, mt, id, pr) {
*index += [{val: id, pos: ebml_w.writer.tell()}];
ebml_w.start_tag(tag_items_data_item);
#debug("encode_info_for_class: doing %s %d", nm, id);
- encode_privacy(ebml_w, ci.node.privacy);
+ encode_privacy(ebml_w, pr);
encode_name(ebml_w, nm);
encode_path(ebml_w, path, ast_map::path_name(nm));
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
ebml_w.end_tag();
}
class_method(m) {
- *index += [{val: m.id, pos: ebml_w.writer.tell()}];
- /* Not sure whether we really need to have two indices,
- but it works for now -- tjc */
- *global_index += [{val: m.id, pos: ebml_w.writer.tell()}];
- let impl_path = path + [ast_map::path_name(m.ident)];
- /*
- Recall methods are (currently) monomorphic, and we don't
- repeat the class's ty params in the method decl
- */
- #debug("encode_info_for_class: doing %s %d", m.ident, m.id);
- encode_info_for_method(ecx, ebml_w, impl_path,
- should_inline(m.attrs), id, m, []);
+ alt m.privacy {
+ pub {
+ *index += [{val: m.id, pos: ebml_w.writer.tell()}];
+ /* Not sure whether we really need to have two indices,
+ but it works for now -- tjc */
+ *global_index += [{val: m.id, pos: ebml_w.writer.tell()}];
+ let impl_path = path + [ast_map::path_name(m.ident)];
+ /*
+ Recall methods are (currently) monomorphic, and we don't
+ repeat the class's ty params in the method decl
+ */
+ #debug("encode_info_for_class: doing %s %d", m.ident, m.id);
+ encode_info_for_method(ecx, ebml_w, impl_path,
+ should_inline(m.attrs), id, m, []);
+ }
+ _ { /* don't encode private methods */ }
+ }
}
}
}
encode_def_id(ebml_w, local_def(f.id));
ebml_w.end_tag();
}
- for mt in ms {
- alt mt.privacy {
+ for m in ms {
+ alt m.privacy {
priv { /* do nothing */ }
pub {
- let m = mt.meth;
ebml_w.start_tag(tag_item_method);
#debug("Writing %s %d", m.ident, m.id);
encode_family(ebml_w, purity_fn_family(m.decl.purity));
let p = extend(cx, i.ident);
for ci in items {
// only need to handle methods
- alt ci.node.decl {
- class_method(m) {
- map_method(d_id, p, m, cx);
- }
+ alt ci.node {
+ class_method(m) { map_method(d_id, p, m, cx); }
_ {}
}
}
alt item.node {
item_class(tps, items, ctor) {
v.visit_ty_params(tps, cx, v);
- vec::map::<@class_item, ()>(items,
- {|i| v.visit_class_item(i.span,
- i.node.privacy, i.node.decl, cx, v); });
+ vec::map::<@class_member, ()>(items,
+ {|i| v.visit_class_item(i, cx, v); });
v.visit_fn(visit::fk_ctor(item.ident, tps), ctor.node.dec,
ctor.node.body, ctor.span, ctor.node.id,
@{in_ctor: some(ctor.node.self_id) with *cx}, v);
mie_import_ident(node_id, span),
mie_item(@ast::item),
mie_class_item(node_id, /* parent class name */
- @ast::class_item), /* class member */
+ @ast::class_member), /* class member */
mie_native_item(@ast::native_item),
mie_enum_variant(/* variant index */uint,
/*parts of enum item*/ [variant],
ctor_scope, v);
/* visit the items */
for cm in members {
- alt cm.node.decl {
+ alt cm.node {
class_method(m) {
let msc = cons(scope_method(m.self_id, tps + m.tps),
@class_scope);
visit_fn_with_scope(e,
visit::fk_item_fn(m.ident, tps), m.decl, m.body,
m.span, m.id, msc, v); }
- instance_var(_,t,_,_) { v.visit_ty(t, class_scope, v); }
+ instance_var(_,t,_,_,_) { v.visit_ty(t, class_scope, v); }
}
}
}
using the mod_index stuff
*/
fn lookup_in_class(parent_id: def_id,
- members: [@class_item], name: ident)
+ members: [@class_member], name: ident)
-> option<def> {
for m in members {
- alt m.node.decl {
- instance_var(v_name,_,_,id) {
+ alt m.node {
+ instance_var(v_name,_,_,id,_) {
if v_name == name {
ret some(def_class_field(parent_id, local_def(id)));
}
}
}
mie_class_item(parent_id, class_item) {
- alt class_item.node.decl {
- instance_var(_,_,_,id) {
+ alt class_item.node {
+ instance_var(_,_,_,id,_) {
ret some(ast::def_class_field(local_def(parent_id),
local_def(id)));
}
// Translate methods
let (_, ms) = ast_util::split_class_items(items);
- impl::trans_impl(ccx, *path, item.ident,
- vec::map(ms, {|m| m.meth}), tps);
+ impl::trans_impl(ccx, *path, item.ident, ms, tps);
}
_ {/* fall through */ }
}
item_class(tps, items, ctor) {
cx.rmap.insert(ctor.node.id, ());
for vec::each(items) {|item|
- alt item.node.decl {
+ alt item.node {
class_method(m) {
cx.rmap.insert(m.id, ());
if tps.len() > 0u ||
type method = {ident: ast::ident,
tps: @[param_bounds],
fty: fn_ty,
- purity: ast::purity};
+ purity: ast::purity,
+ privacy: ast::privacy};
type constr_table = hashmap<ast::node_id, [constr]>;
alt cx.items.find(did.node) {
some(ast_map::node_item(@{node: item_class(_,items,_), _}, _)) {
let (_,ms) = split_class_items(items);
- vec::map(ms, {|m| {name: m.meth.ident, id: m.meth.id,
+ vec::map(ms, {|m| {name: m.ident, id: m.id,
privacy: m.privacy}})
}
_ {
/* Given a class def_id and a method name, return the method's
def_id. Needed so we can do static dispatch for methods
- Fails if the requested method is private */
+ Doesn't care about the method's privacy. (It's assumed that
+ the caller already checked that.)
+*/
fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
sp: span) -> def_id {
if check is_local(did) {
let ms = lookup_class_method_ids(cx, did);
for m in ms {
- if m.name == name && m.privacy == ast::pub {
+ if m.name == name {
ret ast_util::local_def(m.id);
}
}
- cx.sess.span_fatal(sp, #fmt("Class doesn't have a public method \
+ cx.sess.span_fatal(sp, #fmt("Class doesn't have a method \
named %s", name));
}
else {
}
}
-fn class_field_tys(items: [@class_item]) -> [field_ty] {
+fn class_field_tys(items: [@class_member]) -> [field_ty] {
let mut rslt = [];
for it in items {
- alt it.node.decl {
- instance_var(nm, _, cm, id) {
+ alt it.node {
+ instance_var(nm, _, cm, id, privacy) {
rslt += [{ident: nm, id: ast_util::local_def(id),
- privacy: it.node.privacy, mutability: cm}];
- }
- class_method(_) {
+ privacy: privacy, mutability: cm}];
}
+ class_method(_) { }
}
}
rslt
next_region_var_id: @mut int,
ccx: @crate_ctxt};
+// Determines whether the given node ID is a use of the def of
+// the self ID for the current method, if there is one
+fn self_ref(fcx: @fn_ctxt, id: ast::node_id) -> bool {
+ let node_def = alt fcx.ccx.tcx.def_map.find(id) {
+ none { ret false; }
+ some(d) { d } };
+ alt get_self_info(fcx.ccx) {
+ some(self_impl(_, slf_def)) {
+ alt node_def {
+ ast::def_self(slf_actual) { slf_def == slf_actual }
+ _ { false }
+ }
+ }
+ none { false }
+ }
+}
fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> int {
alt fcx.locals.find(id) {
fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method {
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl),
- purity: m.decl.purity}
+ purity: m.decl.purity, privacy: m.privacy}
}
fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method)
-> ty::method {
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl),
- purity: m.decl.purity}
+ // assume public, because this is only invoked on iface methods
+ purity: m.decl.purity, privacy: ast::pub}
}
// A convenience function to use a crate_ctxt to resolve names for
}
ast_map::node_item(@{node: ast::item_class(_,its,_), _}, _) {
let (_,ms) = split_class_items(its);
- // Only public methods need to be stored
- let ps = ast_util::public_methods(ms);
- store_methods::<@ast::method>(tcx, id, ps, {|m|
+ // All methods need to be stored, since lookup_method
+ // relies on the same method cache for self-calls
+ store_methods::<@ast::method>(tcx, id, ms, {|m|
ty_of_method(tcx, m_collect, m)});
}
}
mk_ty_params(tcx, tps).params);
// Need to convert all methods so we can check internal
// references to private methods
- convert_methods(tcx, ast_util::ignore_privacy(methods), @[],
- some(selfty));
+ convert_methods(tcx, methods, @[], some(selfty));
}
_ {
// This call populates the type cache with the converted type
}
fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id,
- name: ast::ident, ty: ty::t, tps: [ty::t])
+ name: ast::ident, ty: ty::t, tps: [ty::t],
+ include_private: bool)
-> option<method_origin> {
- alt lookup_method_inner(fcx, expr, name, ty) {
+ alt lookup_method_inner(fcx, expr, name, ty, include_private) {
some({method_ty: fty, n_tps: method_n_tps, substs, origin, self_sub}) {
let tcx = fcx.ccx.tcx;
let mut substs = substs;
}
fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
- tps: [ty::t], parent: method_kind, name: ast::ident, sp: span)
+ tps: [ty::t], parent: method_kind, name: ast::ident, sp: span,
+ include_private: bool)
-> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t],
origin: method_origin, self_sub: option<self_subst>}> {
#debug("lookup_method_inner_: %? %? %s", ms, parent, name);
tcx.sess.span_fatal(
sp, "can not call a generic method through a \
boxed iface");
+ } else if m.privacy == ast::priv && !include_private {
+ tcx.sess.span_fatal(
+ sp, "Call to private method not allowed outside \
+ its defining class");
}
ret some({method_ty: fty,
n_tps: vec::len(*m.tps),
// look up method named <name>
// its id is did
let m_declared = ty::lookup_class_method_by_name(tcx,
- parent_id, name, sp);
+ parent_id, name, sp);
method_static(m_declared)
}
an_iface(did) { method_iface(did, i) }
}
fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
- name: ast::ident, ty: ty::t)
+ name: ast::ident, ty: ty::t,
+ include_private: bool)
-> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t],
origin: method_origin,
self_sub: option<self_subst>}> {
}
ty::ty_iface(did, tps) {
alt lookup_method_inner_(tcx, *ty::iface_methods(tcx, did), tps,
- an_iface(did), name, expr.span) {
+ an_iface(did), name, expr.span, include_private) {
some(r) { ret some(r); }
none { }
}
}
ty::ty_class(did, tps) {
alt lookup_method_inner_(tcx, *ty::iface_methods(tcx, did), tps,
- cls(did), name, expr.span) {
+ cls(did), name, expr.span, include_private) {
some(r) { ret some(r); }
none { }
}
opname: str, args: [option<@ast::expr>])
-> option<(ty::t, bool)> {
let callee_id = ast_util::op_expr_callee_id(op_ex);
- alt lookup_method(fcx, op_ex, callee_id, opname, self_t, []) {
+ alt lookup_method(fcx, op_ex, callee_id, opname, self_t, [], false) {
some(origin) {
let mut method_ty = ty::node_id_to_type(fcx.ccx.tcx, callee_id);
method_ty = universally_quantify_regions(fcx, region_env(),
}
}
ty::ty_class(base_id, _params) {
+ // This is just for fields -- the same code handles
+ // methods in both classes and ifaces
+
// (1) verify that the class id actually has a field called
// field
#debug("class named %s", ty_to_str(tcx, base_t));
determines whether we look at all fields or only public
ones
*/
- let node_def = lookup_def(fcx, base.span, base.id);
- let cls_items = alt get_self_info(fcx.ccx) {
- some(self_impl(_, n_id)) if alt node_def {
- ast::def_self(base_id) { base_id == n_id }
- _ { false }} {
- // base expr is "self" -- consider all fields
- ty::lookup_class_fields(tcx, base_id)
- }
- _ { lookup_public_fields(tcx, base_id) }
+ let cls_items = if self_ref(fcx, base.id) {
+ // base expr is "self" -- consider all fields
+ ty::lookup_class_fields(tcx, base_id)
+ }
+ else {
+ lookup_public_fields(tcx, base_id)
};
- alt lookup_field_ty(tcx, base_id, cls_items, field) {
+ alt lookup_field_ty(tcx, base_id, cls_items, field) {
some(field_ty) {
// (2) look up what field's type is, and return it
// FIXME: actually instantiate any type params
}
if !handled {
let tps = vec::map(tys, {|ty| ast_ty_to_ty_crate(fcx.ccx, ty)});
- alt lookup_method(fcx, expr, expr.id, field, expr_t, tps) {
+ alt lookup_method(fcx, expr, expr.id, field, expr_t, tps,
+ self_ref(fcx, base.id)) {
some(origin) {
fcx.ccx.method_map.insert(id, origin);
}
let p_ty = expr_ty(tcx, p);
- alt lookup_method(fcx, p, alloc_id, "alloc", p_ty, []) {
+ alt lookup_method(fcx, p, alloc_id, "alloc", p_ty, [], false) {
some(origin) {
fcx.ccx.method_map.insert(alloc_id, origin);
false, none);
}
-fn class_types(ccx: @crate_ctxt, members: [@ast::class_item]) -> class_map {
+fn class_types(ccx: @crate_ctxt, members: [@ast::class_member]) -> class_map {
let rslt = int_hash::<ty::t>();
for m in members {
- alt m.node.decl {
- ast::instance_var(_,t,_,id) {
+ alt m.node {
+ ast::instance_var(_,t,_,id,_) {
rslt.insert(id, ast_ty_to_ty(ccx.tcx, m_collect, t));
}
ast::class_method(mth) {
rslt.insert(mth.id, ty::mk_fn(ccx.tcx,
- ty_of_method(ccx.tcx, m_collect, mth).fty));
+ ty_of_method(ccx.tcx, m_collect, mth).fty));
}
}
}
}
fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
- cm: ast::class_member) {
- alt cm {
- ast::instance_var(_,t,_,_) {
- }
+ cm: @ast::class_member) {
+ alt cm.node {
+ ast::instance_var(_,t,_,_,_) { }
ast::class_method(m) {
ccx.self_infos += [self_impl(class_t, m.self_id)];
check_method(ccx, m);
ctor.node.body, ctor.node.id, false, none);
vec::pop(class_ccx.self_infos);
// typecheck the members
- for m in members { check_class_member(class_ccx, class_t,
- m.node.decl); }
+ for m in members { check_class_member(class_ccx, class_t, m); }
}
_ {/* nothing to do */ }
}
#[auto_serialize]
type method = {ident: ident, attrs: [attribute],
tps: [ty_param], decl: fn_decl, body: blk,
- id: node_id, span: span, self_id: node_id};
+ id: node_id, span: span, self_id: node_id,
+ privacy: privacy}; // privacy is always public, unless it's a
+ // class method
#[auto_serialize]
type _mod = {view_items: [@view_item], items: [@item]};
item_res(fn_decl /* dtor */, [ty_param], blk,
node_id /* dtor id */, node_id /* ctor id */),
item_class([ty_param], /* ty params for class */
- [@class_item], /* methods, etc. */
- /* (not including ctor) */
+ [@class_member], /* methods, etc. */
+ /* (not including ctor) */
class_ctor
),
item_iface([ty_param], [ty_method]),
}
#[auto_serialize]
-type class_item_ = {privacy: privacy, decl: class_member};
+type class_member = spanned<class_member_>;
#[auto_serialize]
-type class_item = spanned<class_item_>;
-
-#[auto_serialize]
-enum class_member {
- instance_var(ident, @ty, class_mutability, node_id),
+enum class_member_ {
+ instance_var(ident, @ty, class_mutability, node_id, privacy),
class_method(@method)
// without constrained types, have to duplicate some stuff. or factor out
// item to separate out things with type params?
// for reserving this id.
fn op_expr_callee_id(e: @expr) -> node_id { e.id - 1 }
-pure fn class_item_ident(ci: @class_item) -> ident {
- alt ci.node.decl {
- instance_var(i,_,_,_) { i }
+pure fn class_item_ident(ci: @class_member) -> ident {
+ alt ci.node {
+ instance_var(i,_,_,_,_) { i }
class_method(it) { it.ident }
}
}
type ivar = {ident: ident, ty: @ty, cm: class_mutability,
id: node_id, privacy: privacy};
-type cmethod = {privacy: privacy, meth: @method};
-
-fn public_methods(cms: [cmethod]) -> [@method] {
- vec::filter_map(cms, {|cm| alt cm.privacy {
- pub { some(cm.meth) }
- _ { none }}})
-}
-
-fn ignore_privacy(cms: [cmethod]) -> [@method] {
- vec::map(cms, {|cm| cm.meth})
+fn public_methods(ms: [@method]) -> [@method] {
+ vec::filter(ms, {|m| alt m.privacy {
+ pub { true }
+ _ { false }}})
}
-fn split_class_items(cs: [@class_item]) -> ([ivar], [cmethod]) {
+fn split_class_items(cs: [@class_member]) -> ([ivar], [@method]) {
let mut vs = [], ms = [];
for c in cs {
- alt c.node.decl {
- instance_var(i, t, cm, id) {
- vs += [{ident: i, ty: t, cm: cm, id: id, privacy: c.node.privacy}];
+ alt c.node {
+ instance_var(i, t, cm, id, privacy) {
+ vs += [{ident: i, ty: t, cm: cm, id: id, privacy: privacy}];
}
- class_method(m) { ms += [{privacy: c.node.privacy, meth: m}]; }
+ class_method(m) { ms += [m]; }
}
}
(vs, ms)
}
+pure fn class_member_privacy(ci: @class_member) -> privacy {
+ alt ci.node {
+ instance_var(_, _, _, _, p) { p }
+ class_method(m) { m.privacy }
+ }
+}
+
impl inlined_item_methods for inlined_item {
fn ident() -> ident {
alt self {
fold_view_item: fn@(view_item_, ast_fold) -> view_item_,
fold_native_item: fn@(&&@native_item, ast_fold) -> @native_item,
fold_item: fn@(&&@item, ast_fold) -> @item,
- fold_class_item: fn@(&&@class_item, ast_fold) -> @class_item,
+ fold_class_item: fn@(&&@class_member, ast_fold) -> @class_member,
fold_item_underscore: fn@(item_, ast_fold) -> item_,
fold_method: fn@(&&@method, ast_fold) -> @method,
fold_block: fn@(blk_, span, ast_fold) -> (blk_, span),
fold_view_item: fn@(&&@view_item) -> @view_item,
fold_native_item: fn@(&&@native_item) -> @native_item,
fold_item: fn@(&&@item) -> @item,
- fold_class_item: fn@(&&@class_item) -> @class_item,
+ fold_class_item: fn@(&&@class_member) -> @class_member,
fold_item_underscore: fn@(item_) -> item_,
fold_method: fn@(&&@method) -> @method,
fold_block: fn@(blk) -> blk,
fn nf_view_item_dummy(&&_v: @view_item) -> @view_item { fail; }
fn nf_native_item_dummy(&&_n: @native_item) -> @native_item { fail; }
fn nf_item_dummy(&&_i: @item) -> @item { fail; }
-fn nf_class_item_dummy(&&_ci: @class_item) -> @class_item { fail; }
+fn nf_class_item_dummy(&&_ci: @class_member) -> @class_member { fail; }
fn nf_item_underscore_dummy(_i: item_) -> item_ { fail; }
fn nf_method_dummy(&&_m: @method) -> @method { fail; }
fn nf_blk_dummy(_b: blk) -> blk { fail; }
span: fld.new_span(i.span)};
}
-fn noop_fold_class_item(&&ci: @class_item, fld: ast_fold)
- -> @class_item {
- @{node: {
- privacy:ci.node.privacy,
- decl:
- alt ci.node.decl {
- instance_var(ident, t, cm, id) {
- instance_var(ident, fld.fold_ty(t), cm, id)
+fn noop_fold_class_item(&&ci: @class_member, fld: ast_fold)
+ -> @class_member {
+ @{node: alt ci.node {
+ instance_var(ident, t, cm, id, p) {
+ instance_var(ident, fld.fold_ty(t), cm, id, p)
}
class_method(m) { class_method(fld.fold_method(m)) }
- }},
- span: fld.new_span(ci.span)}
+ },
+ span: ci.span}
}
fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
body: fld.fold_block(m.body),
id: fld.new_id(m.id),
span: fld.new_span(m.span),
- self_id: fld.new_id(m.self_id)};
+ self_id: fld.new_id(m.self_id),
+ privacy: m.privacy};
}
ret afp.fold_item(i, f);
}
fn f_class_item(afp: ast_fold_precursor, f: ast_fold,
- &&ci: @class_item) -> @class_item {
- @{node:
- {privacy:ci.node.privacy,
- decl:
- alt ci.node.decl {
- instance_var(nm, t, mt, id) {
+ &&ci: @class_member) -> @class_member {
+ @{node: alt ci.node {
+ instance_var(nm, t, mt, id, p) {
instance_var(nm, f_ty(afp, f, t),
- mt, id)
+ mt, id, p)
}
class_method(m) {
class_method(afp.fold_method(m, f))
}
- }}, span: afp.new_span(ci.span)}
+ }, span: afp.new_span(ci.span)}
}
fn f_item_underscore(afp: ast_fold_precursor, f: ast_fold, i: item_) ->
item_ {
}
/* assumes "let" token has already been consumed */
-fn parse_instance_var(p:parser) -> (ast::class_member, codemap::span) {
+fn parse_instance_var(p:parser, pr: ast::privacy) -> @ast::class_member {
let mut is_mutbl = ast::class_immutable;
let lo = p.span.lo;
if eat_word(p, "mut") || eat_word(p, "mutable") {
let name = parse_ident(p);
expect(p, token::COLON);
let ty = parse_ty(p, false);
- ret (ast::instance_var(name, ty, is_mutbl, p.get_id()),
- ast_util::mk_sp(lo, p.last_span.hi));
+ ret @{node: ast::instance_var(name, ty, is_mutbl, p.get_id(), pr),
+ span: ast_util::mk_sp(lo, p.last_span.hi)};
}
fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
}
}
-fn parse_method(p: parser) -> @ast::method {
+fn parse_method(p: parser, pr: ast::privacy) -> @ast::method {
let attrs = parse_outer_attributes(p);
let lo = p.span.lo, pur = parse_fn_purity(p);
let ident = parse_method_name(p);
let attrs = attrs + inner_attrs;
@{ident: ident, attrs: attrs, tps: tps, decl: decl, body: body,
id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi),
- self_id: p.get_id()}
+ self_id: p.get_id(), privacy: pr}
}
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
let ty = parse_ty(p, false);
let mut meths = [];
expect(p, token::LBRACE);
- while !eat(p, token::RBRACE) { meths += [parse_method(p)]; }
+ while !eat(p, token::RBRACE) { meths += [parse_method(p, ast::pub)]; }
ret mk_item(p, lo, p.last_span.hi, ident,
ast::item_impl(tps, ifce, ty, meths), attrs);
}
let class_path = ident_to_path(p.last_span, class_name);
let ty_params = parse_ty_params(p);
expect(p, token::LBRACE);
- let mut items: [@ast::class_item] = [];
+ let mut ms: [@ast::class_member] = [];
let ctor_id = p.get_id();
let mut the_ctor : option<(ast::fn_decl, ast::blk, codemap::span)> = none;
while p.token != token::RBRACE {
alt parse_class_item(p, class_path) {
- ctor_decl(a_fn_decl, blk, s) {
+ ctor_decl(a_fn_decl, blk, s) {
the_ctor = some((a_fn_decl, blk, s));
}
- plain_decl(a_decl, s) {
- items += [@{node: {privacy: ast::pub, decl: a_decl},
- span: s}];
- }
- priv_decls(some_decls) {
- items += vec::map(some_decls, {|p|
- let (d, s) = p;
- @{node: {privacy: ast::priv, decl: d},
- span: s}});
- }
+ members(mms) { ms += mms; }
}
}
p.bump();
some((ct_d, ct_b, ct_s)) {
ret mk_item(p, lo, p.last_span.hi,
class_name,
- ast::item_class(ty_params, items,
+ ast::item_class(ty_params, ms,
{node: {id: ctor_id,
self_id: p.get_id(),
dec: ct_d,
// lets us identify the constructor declaration at
// parse time
-// we don't really want just the fn_decl...
enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span),
- // assumed to be public
- plain_decl(ast::class_member, codemap::span),
- // contents of a priv section --
- // parse_class_item ensures that
- // none of these are a ctor decl
- priv_decls([(ast::class_member, codemap::span)])}
-
- fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents {
+ members([@ast::class_member]) }
+
+fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents {
if eat_word(p, "new") {
let lo = p.last_span.lo;
// Can ctors have attrs?
let mut results = [];
while p.token != token::RBRACE {
if eat_word(p, "let") {
- let a_var = parse_instance_var(p);
+ let a_var = parse_instance_var(p, ast::priv);
expect(p, token::SEMI);
results += [a_var];
}
else {
- let m = parse_method(p);
- results += [(ast::class_method(m), m.span)];
+ let m = parse_method(p, ast::priv);
+ results += [@{node: ast::class_method(m), span: m.span}];
}
}
p.bump();
- ret priv_decls(results);
+ ret members(results);
}
else {
// Probably need to parse attrs
ret if eat_word(p, "let") {
- let (a_var, a_span) = parse_instance_var(p);
+ let ivar = parse_instance_var(p, ast::pub);
expect(p, token::SEMI);
- plain_decl(a_var, a_span)
+ members([ivar])
}
else {
- let m = parse_method(p);
- plain_decl(ast::class_method(m), m.span)
+ let m = parse_method(p, ast::pub);
+ members([@{node: ast::class_method(m), span: m.span}])
}
}
}
*/
hardbreak_if_not_bol(s);
maybe_print_comment(s, ci.span.lo);
- alt ci.node.privacy {
+ let pr = ast_util::class_member_privacy(ci);
+ alt pr {
ast::priv {
head(s, "priv");
bopen(s);
}
_ {}
}
- alt ci.node.decl {
- ast::instance_var(nm, t, mt, _) {
+ alt ci.node {
+ ast::instance_var(nm, t, mt, _,_) {
word_nbsp(s, "let");
alt mt {
ast::class_mutable { word_nbsp(s, "mut"); }
print_method(s, m);
}
}
- alt ci.node.privacy {
+ alt pr {
ast::priv { bclose(s, ci.span); }
_ {}
}
visit_ty_params: fn@([ty_param], E, vt<E>),
visit_constr: fn@(@path, span, node_id, E, vt<E>),
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
- visit_class_item: fn@(span, privacy, class_member, E, vt<E>)};
+ visit_class_item: fn@(@class_member, E, vt<E>)};
fn default_visitor<E>() -> visitor<E> {
ret @{visit_mod: bind visit_mod::<E>(_, _, _, _, _),
visit_ty_params: bind visit_ty_params::<E>(_, _, _),
visit_constr: bind visit_constr::<E>(_, _, _, _, _),
visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _),
- visit_class_item: bind visit_class_item::<E>(_,_,_,_,_)};
+ visit_class_item: bind visit_class_item::<E>(_,_,_)};
}
fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
item_class(tps, members, ctor) {
v.visit_ty_params(tps, e, v);
for m in members {
- v.visit_class_item(m.span, m.node.privacy, m.node.decl, e, v);
+ v.visit_class_item(m, e, v);
}
// make up a fake fn so as to call visit_fn on the ctor
v.visit_fn(fk_ctor(i.ident, tps), ctor.node.dec,
}
}
-fn visit_class_item<E>(_s: span, _p: privacy, cm: class_member,
- e:E, v:vt<E>) {
- alt cm {
- instance_var(ident, t, mt, id) {
+fn visit_class_item<E>(cm: @class_member, e:E, v:vt<E>) {
+ alt cm.node {
+ instance_var(_, t, _, _, _) {
v.visit_ty(t, e, v);
}
class_method(m) {
visit_ty_params: fn@([ty_param]),
visit_constr: fn@(@path, span, node_id),
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
- visit_class_item: fn@(span, privacy, class_member)};
+ visit_class_item: fn@(@class_member)};
fn simple_ignore_ty(_t: @ty) {}
visit_constr: fn@(_p: @path, _sp: span, _id: node_id) { },
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
_id: node_id) { },
- visit_class_item: fn@(_s: span, _p: privacy, _c: class_member) {}
+ visit_class_item: fn@(_c: @class_member) {}
};
}
} else {
bind v_ty(v.visit_ty, _, _, _)
};
- fn v_class_item(f: fn@(span, privacy, class_member),
- s:span, p:privacy, cm: class_member, &&e: (),
+ fn v_class_item(f: fn@(@class_member),
+ cm: @class_member, &&e: (),
v: vt<()>) {
- f(s, p, cm);
- visit_class_item(s, p, cm, e, v);
+ f(cm);
+ visit_class_item(cm, e, v);
}
ret mk_vt(@{visit_mod: bind v_mod(v.visit_mod, _, _, _, _, _),
visit_view_item: bind v_view_item(v.visit_view_item, _, _, _),
visit_constr: bind v_constr(v.visit_constr, _, _, _, _, _),
visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _),
visit_class_item: bind v_class_item(v.visit_class_item, _, _,
- _, _, _)
+ _)
});
}
-// error-pattern:attempted access of field nap on type
+// error-pattern:Call to private method not allowed
class cat {
priv {
let mut meows : uint;
fn play() {
meows += 1u;
- nap();
+ self.nap();
}
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
}