Allow explicit self-calls within classes

Allow writing self.f() within a class that has a method f. In a future
commit, this syntax will be required. For now, you can write either
self.f() or f().

I added a "privacy" field to all methods (whether class methods or not),
which allowed me to refactor the AST somewhat (getting rid of the
class_item type; now there's just class_member).
This commit is contained in:
Tim Chevalier 2012-03-28 18:50:33 -07:00
parent fe610f04d8
commit f7bbe537c1
18 changed files with 201 additions and 198 deletions

View file

@ -218,10 +218,9 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
}
},
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(_) {

View file

@ -431,7 +431,7 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
'u' { ast::unsafe_fn }
'f' { ast::impure_fn }
'p' { ast::pure_fn }
}}];
}, privacy: ast::pub}];
}
@result
}

View file

@ -83,13 +83,13 @@ fn encode_native_module_item_paths(ebml_w: ebml::writer, nmod: native_mod,
}
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);
@ -368,7 +368,7 @@ fn encode_privacy(ebml_w: ebml::writer, privacy: privacy) {
/* 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 [];
@ -376,12 +376,12 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
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));
@ -390,6 +390,8 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
ebml_w.end_tag();
}
class_method(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 */
@ -403,6 +405,9 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_info_for_method(ecx, ebml_w, impl_path,
should_inline(m.attrs), id, m, []);
}
_ { /* don't encode private methods */ }
}
}
}
}
*index
@ -581,11 +586,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
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));

View file

@ -182,10 +182,8 @@ fn map_item(i: @item, cx: ctx, v: vt) {
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); }
_ {}
}
}

View file

@ -216,9 +216,8 @@ fn visit_item(item: @item, &&cx: @ctx, v: visit::vt<@ctx>) {
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);

View file

@ -89,7 +89,7 @@ enum mod_index_entry {
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],
@ -533,14 +533,14 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
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); }
}
}
}
@ -1161,11 +1161,11 @@ fn lookup_in_fn(e: env, name: ident, decl: ast::fn_decl,
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)));
}
@ -1560,8 +1560,8 @@ fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) ->
}
}
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)));
}

View file

@ -4368,8 +4368,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
// 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 */ }
}

View file

@ -101,7 +101,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
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 ||

View file

@ -156,7 +156,8 @@ type param_bounds = @[param_bound];
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]>;
@ -2165,7 +2166,7 @@ fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
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}})
}
_ {
@ -2176,17 +2177,19 @@ fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
/* 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 {
@ -2194,16 +2197,15 @@ fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
}
}
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

View file

@ -83,6 +83,22 @@ type fn_ctxt =
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) {
@ -709,13 +725,14 @@ fn ty_param_bounds(tcx: ty::ctxt, mode: mode, params: [ast::ty_param])
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
@ -939,9 +956,9 @@ mod collect {
}
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)});
}
}
@ -1101,8 +1118,7 @@ mod collect {
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
@ -2011,9 +2027,10 @@ fn impl_self_ty(tcx: ty::ctxt, did: ast::def_id) -> {n_tps: uint, ty: ty::t} {
}
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;
@ -2064,7 +2081,8 @@ enum method_kind {
}
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);
@ -2080,6 +2098,10 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
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),
@ -2102,7 +2124,8 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
}
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>}> {
@ -2145,14 +2168,14 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
}
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 { }
}
@ -2499,7 +2522,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
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(),
@ -3108,6 +3131,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
}
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));
@ -3116,15 +3142,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
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 }} {
let cls_items = if self_ref(fcx, base.id) {
// base expr is "self" -- consider all fields
ty::lookup_class_fields(tcx, base_id)
}
_ { lookup_public_fields(tcx, base_id) }
else {
lookup_public_fields(tcx, base_id)
};
alt lookup_field_ty(tcx, base_id, cls_items, field) {
some(field_ty) {
@ -3140,7 +3163,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
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);
}
@ -3193,7 +3217,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
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);
@ -3665,11 +3689,11 @@ fn check_method(ccx: @crate_ctxt, method: @ast::method) {
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) {
@ -3682,10 +3706,9 @@ fn class_types(ccx: @crate_ctxt, members: [@ast::class_item]) -> class_map {
}
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);
@ -3729,8 +3752,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
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 */ }
}

View file

@ -553,7 +553,9 @@ enum ret_style {
#[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]};
@ -649,7 +651,7 @@ enum 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. */
[@class_member], /* methods, etc. */
/* (not including ctor) */
class_ctor
),
@ -659,14 +661,11 @@ enum item_ {
}
#[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?

View file

@ -262,9 +262,9 @@ pure fn unguarded_pat(a: arm) -> option<[@pat]> {
// 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 }
}
}
@ -272,31 +272,32 @@ pure fn class_item_ident(ci: @class_item) -> 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 public_methods(ms: [@method]) -> [@method] {
vec::filter(ms, {|m| alt m.privacy {
pub { true }
_ { false }}})
}
fn ignore_privacy(cms: [cmethod]) -> [@method] {
vec::map(cms, {|cm| cm.meth})
}
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 {

View file

@ -27,7 +27,7 @@ type ast_fold_precursor =
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),
@ -54,7 +54,7 @@ type a_f =
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,
@ -84,7 +84,7 @@ fn nf_crate_directive_dummy(&&_c: @crate_directive) -> @crate_directive {
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; }
@ -240,18 +240,15 @@ fn noop_fold_item(&&i: @item, fld: ast_fold) -> @item {
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_ {
@ -302,7 +299,8 @@ fn noop_fold_method(&&m: @method, fld: ast_fold) -> @method {
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};
}
@ -655,19 +653,16 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
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_ {

View file

@ -1681,7 +1681,7 @@ fn parse_let(p: parser) -> @ast::decl {
}
/* 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") {
@ -1693,8 +1693,8 @@ fn parse_instance_var(p:parser) -> (ast::class_member, codemap::span) {
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 {
@ -1986,7 +1986,7 @@ fn parse_method_name(p: parser) -> ast::ident {
}
}
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);
@ -1996,7 +1996,7 @@ fn parse_method(p: parser) -> @ast::method {
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 {
@ -2034,7 +2034,7 @@ fn parse_item_impl(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);
}
@ -2070,7 +2070,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
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 {
@ -2078,16 +2078,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
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();
@ -2095,7 +2086,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
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,
@ -2112,14 +2103,8 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
// 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)])}
members([@ast::class_member]) }
fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents {
if eat_word(p, "new") {
@ -2140,28 +2125,28 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span),
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}])
}
}
}

View file

@ -506,7 +506,8 @@ fn print_item(s: ps, &&item: @ast::item) {
*/
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);
@ -514,8 +515,8 @@ fn print_item(s: ps, &&item: @ast::item) {
}
_ {}
}
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"); }
@ -530,7 +531,7 @@ fn print_item(s: ps, &&item: @ast::item) {
print_method(s, m);
}
}
alt ci.node.privacy {
alt pr {
ast::priv { bclose(s, ci.span); }
_ {}
}

View file

@ -55,7 +55,7 @@ type visitor<E> =
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>(_, _, _, _, _),
@ -73,7 +73,7 @@ fn default_visitor<E>() -> visitor<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>) {
@ -139,7 +139,7 @@ fn visit_item<E>(i: @item, 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,
@ -155,10 +155,9 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
}
}
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) {
@ -427,7 +426,7 @@ type simple_visitor =
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) {}
@ -448,7 +447,7 @@ fn default_simple_visitor() -> simple_visitor {
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) {}
};
}
@ -523,11 +522,11 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
} 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, _, _, _),
@ -546,7 +545,7 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
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, _, _,
_, _, _)
_)
});
}

View file

@ -1,4 +1,4 @@
// error-pattern:attempted access of field nap on type
// error-pattern:Call to private method not allowed
class cat {
priv {
let mut meows : uint;

View file

@ -8,7 +8,7 @@ class cat {
fn play() {
meows += 1u;
nap();
self.nap();
}
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
}