rustc: Perform some AST surgery to separate out class fields from methods

This commit is contained in:
Patrick Walton 2012-08-15 15:53:58 -07:00
parent 353c632c2d
commit 3038968f28
18 changed files with 301 additions and 308 deletions

View file

@ -717,10 +717,27 @@ type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id};
#[auto_serialize]
enum visibility { public, private, inherited }
#[auto_serialize]
type struct_field_ = {
kind: struct_field_kind,
id: node_id,
ty: @ty
};
#[auto_serialize]
type struct_field = spanned<struct_field_>;
#[auto_serialize]
enum struct_field_kind {
named_field(ident, class_mutability, visibility),
unnamed_field // element of a tuple-like struct
}
#[auto_serialize]
type struct_def = {
traits: ~[@trait_ref], /* traits this class implements */
members: ~[@class_member], /* methods, etc. */
traits: ~[@trait_ref], /* traits this struct implements */
fields: ~[@struct_field], /* fields */
methods: ~[@method], /* methods */
/* (not including ctor or dtor) */
/* ctor is optional, and will soon go away */
ctor: option<class_ctor>,
@ -750,15 +767,6 @@ enum item_ {
item_mac(mac),
}
#[auto_serialize]
type class_member = spanned<class_member_>;
#[auto_serialize]
enum class_member_ {
instance_var(ident, @ty, class_mutability, node_id, visibility),
class_method(@method)
}
#[auto_serialize]
enum class_mutability { class_mutable, class_immutable }

View file

@ -248,7 +248,6 @@ fn map_item(i: @item, cx: ctx, v: vt) {
fn map_struct_def(struct_def: @ast::struct_def, parent_node: ast_node,
ident: ast::ident, id: ast::node_id, cx: ctx, _v: vt) {
let (_, ms) = ast_util::split_class_items(struct_def.members);
// Map trait refs to their parent classes. This is
// so we can find the self_ty
for struct_def.traits.each |p| {
@ -260,7 +259,7 @@ fn map_struct_def(struct_def: @ast::struct_def, parent_node: ast_node,
let d_id = ast_util::local_def(id);
let p = extend(cx, ident);
// only need to handle methods
do vec::iter(ms) |m| { map_method(d_id, p, m, cx); }
do vec::iter(struct_def.methods) |m| { map_method(d_id, p, m, cx); }
}
fn map_view_item(vi: @view_item, cx: ctx, _v: vt) {

View file

@ -295,16 +295,6 @@ pure fn unguarded_pat(a: arm) -> option<~[@pat]> {
if is_unguarded(a) { some(/* FIXME (#2543) */ copy a.pats) } else { none }
}
pure fn class_item_ident(ci: @class_member) -> ident {
match ci.node {
instance_var(i,_,_,_,_) => /* FIXME (#2543) */ copy i,
class_method(it) => /* FIXME (#2543) */ copy it.ident
}
}
type ivar = {ident: ident, ty: @ty, cm: class_mutability,
id: node_id, vis: visibility};
fn public_methods(ms: ~[@method]) -> ~[@method] {
vec::filter(ms,
|m| match m.vis {
@ -313,23 +303,6 @@ fn public_methods(ms: ~[@method]) -> ~[@method] {
})
}
fn split_class_items(cs: ~[@class_member]) -> (~[ivar], ~[@method]) {
let mut vs = ~[], ms = ~[];
for cs.each |c| {
match c.node {
instance_var(i, t, cm, id, vis) => {
vec::push(vs, {ident: /* FIXME (#2543) */ copy i,
ty: t,
cm: cm,
id: id,
vis: vis});
}
class_method(m) => vec::push(ms, m)
}
};
(vs, ms)
}
// extract a ty_method from a trait_method. if the trait_method is
// a default, pull out the useful fields to make a ty_method
fn trait_method_to_ty_method(method: trait_method) -> ty_method {
@ -355,11 +328,11 @@ fn split_trait_methods(trait_methods: ~[trait_method])
(reqd, provd)
}
pure fn class_member_visibility(ci: @class_member) -> visibility {
match ci.node {
instance_var(_, _, _, _, vis) => vis,
class_method(m) => m.vis
}
pure fn struct_field_visibility(field: ast::struct_field) -> visibility {
match field.node.kind {
ast::named_field(_, _, visibility) => visibility,
ast::unnamed_field => ast::public
}
}
trait inlined_item_utils {
@ -570,11 +543,11 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
_id: node_id) {
},
visit_class_item: fn@(c: @class_member) {
match c.node {
instance_var(_, _, _, id,_) => vfn(id),
class_method(_) => ()
}
visit_struct_field: fn@(f: @struct_field) {
vfn(f.node.id);
},
visit_struct_method: fn@(_m: @method) {
}
})
}

View file

@ -24,7 +24,7 @@ trait ast_fold {
fn fold_view_item(&&@view_item) -> @view_item;
fn fold_foreign_item(&&@foreign_item) -> @foreign_item;
fn fold_item(&&@item) -> option<@item>;
fn fold_class_item(&&@class_member) -> @class_member;
fn fold_struct_field(&&@struct_field) -> @struct_field;
fn fold_item_underscore(item_) -> item_;
fn fold_method(&&@method) -> @method;
fn fold_block(blk) -> blk;
@ -55,7 +55,7 @@ type ast_fold_precursor = @{
fold_view_item: fn@(view_item_, ast_fold) -> view_item_,
fold_foreign_item: fn@(&&@foreign_item, ast_fold) -> @foreign_item,
fold_item: fn@(&&@item, ast_fold) -> option<@item>,
fold_class_item: fn@(&&@class_member, ast_fold) -> @class_member,
fold_struct_field: fn@(&&@struct_field, ast_fold) -> @struct_field,
fold_item_underscore: fn@(item_, ast_fold) -> item_,
fold_method: fn@(&&@method, ast_fold) -> @method,
fold_block: fn@(blk_, span, ast_fold) -> (blk_, span),
@ -214,16 +214,12 @@ fn noop_fold_item(&&i: @item, fld: ast_fold) -> option<@item> {
span: fld.new_span(i.span)});
}
fn noop_fold_class_item(&&ci: @class_member, fld: ast_fold)
-> @class_member {
@{node: match ci.node {
instance_var(ident, t, cm, id, p) => {
instance_var(/* FIXME (#2543) */ copy ident,
fld.fold_ty(t), cm, id, p)
}
class_method(m) => class_method(fld.fold_method(m))
},
span: ci.span}
fn noop_fold_struct_field(&&sf: @struct_field, fld: ast_fold)
-> @struct_field {
@{node: {kind: copy sf.node.kind,
id: sf.node.id,
ty: fld.fold_ty(sf.node.ty)},
span: sf.span}
}
fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
@ -295,7 +291,8 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
with dtor}};
return @{
traits: vec::map(struct_def.traits, |p| fold_trait_ref(p, fld)),
members: vec::map(struct_def.members, |x| fld.fold_class_item(x)),
fields: vec::map(struct_def.fields, |f| fold_struct_field(f, fld)),
methods: vec::map(struct_def.methods, |m| fld.fold_method(m)),
ctor: resulting_optional_constructor,
dtor: dtor
};
@ -306,6 +303,13 @@ fn fold_trait_ref(&&p: @trait_ref, fld: ast_fold) -> @trait_ref {
impl_id: fld.new_id(p.impl_id)}
}
fn fold_struct_field(&&f: @struct_field, fld: ast_fold) -> @struct_field {
@{node: {kind: copy f.node.kind,
id: fld.new_id(f.node.id),
ty: fld.fold_ty(f.node.ty)},
span: fld.new_span(f.span)}
}
fn noop_fold_method(&&m: @method, fld: ast_fold) -> @method {
return @{ident: fld.fold_ident(m.ident),
attrs: /* FIXME (#2543) */ copy m.attrs,
@ -570,8 +574,9 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ {
with dtor}};
kind = struct_variant_kind(@{
traits: ~[],
members: vec::map(struct_def.members,
|x| fld.fold_class_item(x)),
fields: vec::map(struct_def.fields,
|f| fld.fold_struct_field(f)),
methods: vec::map(struct_def.methods, |m| fld.fold_method(m)),
ctor: none,
dtor: dtor
})
@ -644,7 +649,7 @@ fn default_ast_fold() -> ast_fold_precursor {
fold_view_item: noop_fold_view_item,
fold_foreign_item: noop_fold_foreign_item,
fold_item: noop_fold_item,
fold_class_item: noop_fold_class_item,
fold_struct_field: noop_fold_struct_field,
fold_item_underscore: noop_fold_item_underscore,
fold_method: noop_fold_method,
fold_block: wrap(noop_fold_block),
@ -692,16 +697,11 @@ impl ast_fold_precursor: ast_fold {
fn fold_item(&&i: @item) -> option<@item> {
return self.fold_item(i, self as ast_fold);
}
fn fold_class_item(&&ci: @class_member) -> @class_member {
@{node: match ci.node {
instance_var(nm, t, mt, id, p) => {
instance_var(/* FIXME (#2543) */ copy nm,
(self as ast_fold).fold_ty(t), mt, id, p)
}
class_method(m) => {
class_method(self.fold_method(m, self as ast_fold))
}
}, span: self.new_span(ci.span)}
fn fold_struct_field(&&sf: @struct_field) -> @struct_field {
@{node: {kind: copy sf.node.kind,
id: sf.node.id,
ty: (self as ast_fold).fold_ty(sf.node.ty)},
span: self.new_span(sf.span)}
}
fn fold_item_underscore(i: item_) ->
item_ {

View file

@ -21,7 +21,7 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
bound_copy, bound_send, bound_trait, bound_owned, box, by_copy,
by_move, by_mutbl_ref, by_ref, by_val, capture_clause,
capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item,
class_immutable, class_member, class_method, class_mutable,
class_immutable, class_mutable,
crate, crate_cfg, crate_directive, decl, decl_item, decl_local,
default_blk, deref, div, enum_def, enum_variant_kind, expl, expr,
expr_, expr_addr_of, expr_match, expr_again, expr_assert,
@ -33,20 +33,21 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
expr_struct, expr_tup, expr_unary, expr_unary_move, expr_vec,
expr_vstore, expr_while, extern_fn, field, fn_decl, foreign_item,
foreign_item_fn, foreign_mod, ident, impure_fn, infer, inherited,
init_assign, init_move, initializer, instance_var, item, item_,
init_assign, init_move, initializer, item, item_,
item_class, item_const, item_enum, item_fn, item_foreign_mod,
item_impl, item_mac, item_mod, item_trait, item_ty, lit, lit_,
lit_bool, lit_float, lit_int, lit_int_unsuffixed, lit_nil,
lit_str, lit_uint, local, m_const, m_imm, m_mutbl, mac_, mac_aq,
mac_ellipsis, mac_invoc, mac_invoc_tt, mac_var, matcher,
match_nonterminal, match_seq, match_tok, method, mode, mt, mul,
mutability, neg, noreturn, not, pat, pat_box, pat_enum,
mutability, named_field, neg, noreturn, not, pat, pat_box, pat_enum,
pat_ident, pat_lit, pat_range, pat_rec, pat_struct, pat_tup,
pat_uniq, pat_wild, path, private, proto, proto_bare,
proto_block, proto_box, proto_uniq, provided, public, pure_fn,
purity, re_anon, re_named, region, rem, required, ret_style,
return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr,
stmt_semi, struct_def, struct_variant_kind, subtract, sty_box,
stmt_semi, struct_def, struct_field, struct_variant_kind,
subtract, sty_box,
sty_by_ref, sty_region, sty_static, sty_uniq, sty_value,
token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn,
@ -94,6 +95,11 @@ enum pexpr {
pexpr(@expr),
}
enum class_member {
field_member(@struct_field),
method_member(@method)
}
/*
So that we can distinguish a class ctor or dtor
from other class members
@ -2043,8 +2049,11 @@ class parser {
let name = self.parse_ident();
self.expect(token::COLON);
let ty = self.parse_ty(false);
return @{node: instance_var(name, ty, is_mutbl, self.get_id(), pr),
span: mk_sp(lo, self.last_span.hi)};
return @field_member(@spanned(lo, self.last_span.hi, {
kind: named_field(name, is_mutbl, pr),
id: self.get_id(),
ty: ty
}));
}
fn parse_stmt(+first_item_attrs: ~[attribute]) -> @stmt {
@ -2556,7 +2565,8 @@ class parser {
{ self.parse_trait_ref_list(token::LBRACE) }
else { ~[] };
self.expect(token::LBRACE);
let mut ms: ~[@class_member] = ~[];
let mut fields: ~[@struct_field] = ~[];
let mut methods: ~[@method] = ~[];
let ctor_id = self.get_id();
let mut the_ctor : option<(fn_decl, ~[attribute], blk,
codemap::span)> = none;
@ -2589,7 +2599,16 @@ class parser {
}
}
}
members(mms) => { ms = vec::append(ms, mms); }
members(mms) => {
for mms.each |mm| {
match mm {
@field_member(struct_field) =>
vec::push(fields, struct_field),
@method_member(the_method_member) =>
vec::push(methods, the_method_member)
}
}
}
}
}
let actual_dtor = do option::map(the_dtor) |dtor| {
@ -2605,7 +2624,8 @@ class parser {
(class_name,
item_class(@{
traits: traits,
members: ms,
fields: move fields,
methods: move methods,
ctor: some({
node: {id: ctor_id,
attrs: ct_attrs,
@ -2621,7 +2641,8 @@ class parser {
(class_name,
item_class(@{
traits: traits,
members: ms,
fields: move fields,
methods: move methods,
ctor: none,
dtor: actual_dtor
}, ty_params),
@ -2647,7 +2668,7 @@ class parser {
return a_var;
} else {
let m = self.parse_method(vis);
return @{node: class_method(m), span: m.span};
return @method_member(m);
}
}
@ -2883,7 +2904,8 @@ class parser {
fn parse_struct_def(path: @path) -> @struct_def {
let mut the_dtor: option<(blk, ~[attribute], codemap::span)> = none;
let mut ms: ~[@class_member] = ~[];
let mut fields: ~[@struct_field] = ~[];
let mut methods: ~[@method] = ~[];
while self.token != token::RBRACE {
match self.parse_class_item(path) {
ctor_decl(*) => {
@ -2906,8 +2928,16 @@ class parser {
}
}
}
members(mms) =>
ms = vec::append(ms, mms)
members(mms) => {
for mms.each |mm| {
match mm {
@field_member(struct_field) =>
vec::push(fields, struct_field),
@method_member(the_method_member) =>
vec::push(methods, the_method_member)
}
}
}
}
}
self.bump();
@ -2922,7 +2952,8 @@ class parser {
return @{
traits: ~[],
members: ms,
fields: move fields,
methods: move methods,
ctor: none,
dtor: actual_dtor
};

View file

@ -629,45 +629,29 @@ fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param],
head(s, ~"drop");
print_block(s, dtor.node.body);
}
for struct_def.members.each |ci| {
/*
FIXME (#1893): collect all private items and print
them in a single "priv" section
tjc: I'm not going to fix this yet b/c we might
change how exports work, including for class items
*/
hardbreak_if_not_bol(s);
maybe_print_comment(s, ci.span.lo);
let pr = ast_util::class_member_visibility(ci);
match pr {
ast::private => {
head(s, ~"priv");
bopen(s);
hardbreak_if_not_bol(s);
}
_ => ()
}
match ci.node {
ast::instance_var(nm, t, mt, _,_) => {
word_nbsp(s, ~"let");
match mt {
ast::class_mutable => word_nbsp(s, ~"mut"),
_ => ()
}
word(s.s, *nm);
word_nbsp(s, ~":");
print_type(s, t);
word(s.s, ~";");
}
ast::class_method(m) => {
print_method(s, m);
}
}
match pr {
ast::private => bclose(s, ci.span),
_ => ()
}
for struct_def.fields.each |field| {
match field.node.kind {
ast::unnamed_field => {} // We don't print here.
ast::named_field(ident, mutability, visibility) => {
hardbreak_if_not_bol(s);
maybe_print_comment(s, field.span.lo);
if visibility == ast::private {
head(s, ~"priv");
bopen(s);
hardbreak_if_not_bol(s);
}
if mutability == ast::class_mutable {
word_nbsp(s, ~"mut");
}
word(s.s, *ident);
word_nbsp(s, ~":");
print_type(s, field.node.ty);
word(s.s, ~";");
}
}
}
for struct_def.methods.each |method| {
print_method(s, method);
}
bclose(s, span);
}

View file

@ -63,7 +63,8 @@ type visitor<E> =
visit_trait_method: fn@(trait_method, E, vt<E>),
visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id, E,
vt<E>),
visit_class_item: fn@(@class_member, E, vt<E>)};
visit_struct_field: fn@(@struct_field, E, vt<E>),
visit_struct_method: fn@(@method, E, vt<E>)};
fn default_visitor<E>() -> visitor<E> {
return @{visit_mod: |a,b,c,d,e|visit_mod::<E>(a, b, c, d, e),
@ -85,7 +86,8 @@ fn default_visitor<E>() -> visitor<E> {
visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
visit_struct_def: |a,b,c,d,e,f|visit_struct_def::<E>(a, b, c,
d, e, f),
visit_class_item: |a,b,c|visit_class_item::<E>(a, b, c)};
visit_struct_field: |a,b,c|visit_struct_field::<E>(a, b, c),
visit_struct_method: |a,b,c|visit_struct_method::<E>(a, b, c)};
}
fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
@ -183,13 +185,6 @@ fn visit_enum_def<E>(enum_definition: ast::enum_def, tps: ~[ast::ty_param],
}
}
fn visit_class_item<E>(cm: @class_member, e:E, v:vt<E>) {
match cm.node {
instance_var(_, t, _, _, _) => v.visit_ty(t, e, v),
class_method(m) => visit_method_helper(m, e, v)
}
}
fn skip_ty<E>(_t: @ty, _e: E, _v: vt<E>) {}
fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
@ -332,8 +327,11 @@ fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param],
id: node_id, e: E, v: vt<E>) {
for sd.members.each |m| {
v.visit_class_item(m, e, v);
for sd.fields.each |f| {
v.visit_struct_field(f, e, v);
}
for sd.methods.each |m| {
v.visit_struct_method(m, e, v);
}
for sd.traits.each |p| { visit_path(p.path, e, v); }
do option::iter(sd.ctor) |ctor| {
@ -344,6 +342,14 @@ fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param],
};
}
fn visit_struct_field<E>(sf: @struct_field, e: E, v: vt<E>) {
v.visit_ty(sf.node.ty, e, v);
}
fn visit_struct_method<E>(m: @method, e: E, v: vt<E>) {
visit_method_helper(m, e, v);
}
fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
for b.node.view_items.each |vi| { v.visit_view_item(vi, e, v); }
for b.node.stmts.each |s| { v.visit_stmt(s, e, v); }
@ -492,7 +498,8 @@ type simple_visitor =
visit_ty_method: fn@(ty_method),
visit_trait_method: fn@(trait_method),
visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id),
visit_class_item: fn@(@class_member)};
visit_struct_field: fn@(@struct_field),
visit_struct_method: fn@(@method)};
fn simple_ignore_ty(_t: @ty) {}
@ -517,7 +524,8 @@ fn default_simple_visitor() -> simple_visitor {
visit_trait_method: fn@(_m: trait_method) { },
visit_struct_def: fn@(_sd: @struct_def, _nm: ident,
_tps: ~[ty_param], _id: node_id) { },
visit_class_item: fn@(_c: @class_member) {}
visit_struct_field: fn@(_f: @struct_field) { },
visit_struct_method: fn@(_m: @method) { }
};
}
@ -607,11 +615,14 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
} else {
|a,b,c| v_ty(v.visit_ty, a, b, c)
};
fn v_class_item(f: fn@(@class_member),
cm: @class_member, &&e: (),
v: vt<()>) {
f(cm);
visit_class_item(cm, e, v);
fn v_struct_field(f: fn@(@struct_field), sf: @struct_field, &&e: (),
v: vt<()>) {
f(sf);
visit_struct_field(sf, e, v);
}
fn v_struct_method(f: fn@(@method), m: @method, &&e: (), v: vt<()>) {
f(m);
visit_struct_method(m, e, v);
}
return mk_vt(@{visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e),
visit_view_item: |a,b,c|
@ -639,8 +650,10 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
v_trait_method(v.visit_trait_method, a, b, c),
visit_struct_def: |a,b,c,d,e,f|
v_struct_def(v.visit_struct_def, a, b, c, d, e, f),
visit_class_item: |a,b,c|
v_class_item(v.visit_class_item, a, b, c)
visit_struct_field: |a,b,c|
v_struct_field(v.visit_struct_field, a, b, c),
visit_struct_method: |a,b,c|
v_struct_method(v.visit_struct_method, a, b, c)
});
}

View file

@ -745,11 +745,12 @@ fn get_class_fields(cdata: cmd, id: ast::node_id) -> ~[ty::field_ty] {
}
fn family_has_type_params(fam_ch: char) -> bool {
match check fam_ch {
'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' | 'e' => false,
match fam_ch {
'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' | 'e' | 'N' => false,
'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' | 'C'
| 'a' | 'S'
=> true
=> true,
_ => fail fmt!("'%c' is not a family", fam_ch)
}
}

View file

@ -158,19 +158,27 @@ fn encode_foreign_module_item_paths(ebml_w: ebml::writer, nmod: foreign_mod,
}
fn encode_class_item_paths(ebml_w: ebml::writer,
items: ~[@class_member], path: ~[ident], &index: ~[entry<~str>]) {
for items.each |it| {
match ast_util::class_member_visibility(it) {
private => again,
public | inherited => {
let (id, ident) = match it.node {
instance_var(v, _, _, vid, _) => (vid, v),
class_method(it) => (it.id, it.ident)
};
add_to_index(ebml_w, path, index, ident);
encode_named_def_id(ebml_w, ident, local_def(id));
}
}
fields: ~[@ast::struct_field],
methods: ~[@ast::method],
path: ~[ident],
&index: ~[entry<~str>]) {
for fields.each |field| {
match field.node.kind {
ast::named_field(ident, _, visibility) => {
if visibility == private { again; }
let (id, ident) = (field.node.id, ident);
add_to_index(ebml_w, path, index, ident);
encode_named_def_id(ebml_w, ident, local_def(id));
}
ast::unnamed_field => {}
}
}
for methods.each |method| {
if method.vis == private { again; }
let (id, ident) = (method.id, method.ident);
add_to_index(ebml_w, path, index, ident);
encode_named_def_id(ebml_w, ident, local_def(id));
}
}
@ -257,7 +265,8 @@ fn encode_struct_def(ebml_w: ebml::writer,
}
encode_class_item_paths(ebml_w,
struct_def.members,
struct_def.fields,
struct_def.methods,
vec::append_one(path, ident),
index);
}
@ -527,32 +536,38 @@ fn encode_self_type(ebml_w: ebml::writer, self_type: ast::self_ty_) {
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
id: node_id, path: ast_map::path,
class_tps: ~[ty_param],
items: ~[@class_member],
fields: ~[@struct_field],
methods: ~[@method],
global_index: @mut~[entry<int>]) -> ~[entry<int>] {
/* Each class has its own index, since different classes
may have fields with the same name */
let index = @mut ~[];
let tcx = ecx.tcx;
for items.each |ci| {
/* We encode both private and public fields -- need to include
private fields to get the offsets right */
match ci.node {
instance_var(nm, _, mt, id, vis) => {
vec::push(*index, {val: id, pos: ebml_w.writer.tell()});
vec::push(*global_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_visibility(ebml_w, vis);
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));
encode_mutability(ebml_w, mt);
encode_def_id(ebml_w, local_def(id));
ebml_w.end_tag();
for fields.each |field| {
match field.node.kind {
named_field(nm, mt, vis) => {
let id = field.node.id;
vec::push(*index, {val: id, pos: ebml_w.writer.tell()});
vec::push(*global_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_visibility(ebml_w, vis);
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));
encode_mutability(ebml_w, mt);
encode_def_id(ebml_w, local_def(id));
ebml_w.end_tag();
}
unnamed_field => {}
}
class_method(m) => {
match m.vis {
public | inherited => {
}
for methods.each |m| {
match m.vis {
public | inherited => {
vec::push(*index, {val: m.id, pos: ebml_w.writer.tell()});
vec::push(*global_index,
{val: m.id, pos: ebml_w.writer.tell()});
@ -564,10 +579,9 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
vec::append(class_tps, m.tps));
}
_ => { /* don't encode private methods */ }
}
}
}
};
}
*index
}
@ -738,7 +752,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
the index, and the index needs to be in the item for the
class itself */
let idx = encode_info_for_class(ecx, ebml_w, item.id, path, tps,
struct_def.members, index);
struct_def.fields, struct_def.methods,
index);
/* Encode the dtor */
do option::iter(struct_def.dtor) |dtor| {
vec::push(*index, {val: dtor.node.id, pos: ebml_w.writer.tell()});
@ -779,15 +794,20 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
/* Encode def_ids for each field and method
for methods, write all the stuff get_trait_method
needs to know*/
let (fs,ms) = ast_util::split_class_items(struct_def.members);
for fs.each |f| {
ebml_w.start_tag(tag_item_field);
encode_visibility(ebml_w, f.vis);
encode_name(ebml_w, f.ident);
encode_def_id(ebml_w, local_def(f.id));
ebml_w.end_tag();
for struct_def.fields.each |f| {
match f.node.kind {
named_field(ident, mutability, vis) => {
ebml_w.start_tag(tag_item_field);
encode_visibility(ebml_w, vis);
encode_name(ebml_w, ident);
encode_def_id(ebml_w, local_def(f.node.id));
ebml_w.end_tag();
}
unnamed_field => {}
}
}
for ms.each |m| {
for struct_def.methods.each |m| {
match m.vis {
private => { /* do nothing */ }
public | inherited => {

View file

@ -12,7 +12,7 @@ import syntax::ast::{bitand, bitor, bitxor};
import syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send};
import syntax::ast::{bound_trait, binding_mode,
capture_clause, class_ctor, class_dtor};
import syntax::ast::{class_member, class_method, crate, crate_num, decl_item};
import syntax::ast::{crate, crate_num, decl_item};
import syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn};
import syntax::ast::{def_foreign_mod, def_id, def_label, def_local, def_mod};
import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
@ -27,15 +27,15 @@ import syntax::ast::{expr_binary, expr_break, expr_cast, expr_field, expr_fn};
import syntax::ast::{expr_fn_block, expr_index, expr_loop};
import syntax::ast::{expr_path, expr_struct, expr_unary, fn_decl};
import syntax::ast::{foreign_item, foreign_item_fn, ge, gt, ident, trait_ref};
import syntax::ast::{impure_fn, instance_var, item, item_class, item_const};
import syntax::ast::{impure_fn, item, item_class, item_const};
import syntax::ast::{item_enum, item_fn, item_mac, item_foreign_mod};
import syntax::ast::{item_impl, item_mod, item_trait, item_ty, le, local};
import syntax::ast::{local_crate, lt, method, mul, ne, neg, node_id, pat};
import syntax::ast::{pat_enum, pat_ident, path, prim_ty, pat_box, pat_uniq};
import syntax::ast::{pat_lit, pat_range, pat_rec, pat_struct, pat_tup};
import syntax::ast::{pat_wild, provided, required, rem, self_ty_, shl};
import syntax::ast::{stmt_decl, struct_variant_kind, sty_static, subtract};
import syntax::ast::{tuple_variant_kind, ty};
import syntax::ast::{stmt_decl, struct_field, struct_variant_kind};
import syntax::ast::{sty_static, subtract, tuple_variant_kind, ty};
import syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i};
import syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, ty_param};
import syntax::ast::{ty_path, ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8};
@ -1021,23 +1021,16 @@ class Resolver {
// bindings.
let mut method_infos = ~[];
for struct_definition.members.each |class_member| {
match class_member.node {
class_method(method) => {
// XXX: Combine with impl method code below.
method_infos += ~[
@{
did: local_def(method.id),
n_tps: method.tps.len(),
ident: method.ident,
self_type: method.self_ty.node
}
];
for struct_definition.methods.each |method| {
// XXX: Combine with impl method code below.
method_infos += ~[
@{
did: local_def(method.id),
n_tps: method.tps.len(),
ident: method.ident,
self_type: method.self_ty.node
}
instance_var(*) => {
// Don't need to do anything with this.
}
}
];
}
let impl_info = @{
@ -3195,7 +3188,8 @@ class Resolver {
self.resolve_class(item.id,
@copy ty_params,
struct_def.traits,
struct_def.members,
struct_def.fields,
struct_def.methods,
struct_def.ctor,
struct_def.dtor,
visitor);
@ -3435,7 +3429,8 @@ class Resolver {
fn resolve_class(id: node_id,
type_parameters: @~[ty_param],
traits: ~[@trait_ref],
class_members: ~[@class_member],
fields: ~[@struct_field],
methods: ~[@method],
optional_constructor: option<class_ctor>,
optional_destructor: option<class_dtor>,
visitor: ResolveVisitor) {
@ -3479,19 +3474,16 @@ class Resolver {
}
// Resolve methods.
for class_members.each |class_member| {
match class_member.node {
class_method(method) => {
self.resolve_method(MethodRibKind(id,
Provided(method.id)),
method,
outer_type_parameter_count,
visitor);
}
instance_var(_, field_type, _, _, _) => {
self.resolve_type(field_type, visitor);
}
}
for methods.each |method| {
self.resolve_method(MethodRibKind(id, Provided(method.id)),
method,
outer_type_parameter_count,
visitor);
}
// Resolve fields.
for fields.each |field| {
self.resolve_type(field.node.ty, visitor);
}
// Resolve the constructor, if applicable.

View file

@ -5062,8 +5062,7 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def,
// If there are ty params, the ctor will get monomorphized
// Translate methods
let (_, ms) = ast_util::split_class_items(struct_def.members);
impl::trans_impl(ccx, *path, ident, ms, tps);
impl::trans_impl(ccx, *path, ident, struct_def.methods, tps);
}
fn trans_trait(ccx: @crate_ctxt, tps: ~[ast::ty_param],

View file

@ -7,7 +7,7 @@ import driver::session::session;
import syntax::{ast, ast_map};
import ast_map::{path, path_mod, path_name, node_id_to_str};
import driver::session::expect;
import syntax::ast_util::{local_def, split_class_items};
import syntax::ast_util::local_def;
import metadata::csearch;
import back::{link, abi};
import lib::llvm::llvm;
@ -163,8 +163,7 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
}
ast_map::node_item(@{node:
ast::item_class(struct_def, _), _}, _) => {
let (_,ms) = split_class_items(struct_def.members);
method_from_methods(ms, name)
method_from_methods(struct_def.methods, name)
}
}
} else {

View file

@ -126,16 +126,11 @@ fn traverse_public_item(cx: ctx, item: @item) {
traverse_inline_body(cx, dtor.node.body);
}
}
for vec::each(struct_def.members) |item| {
match item.node {
class_method(m) => {
cx.rmap.insert(m.id, ());
if tps.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none {
traverse_inline_body(cx, m.body);
}
}
_ => ()
for vec::each(struct_def.methods) |m| {
cx.rmap.insert(m.id, ());
if tps.len() > 0 ||
attr::find_inline_attr(m.attrs) != attr::ia_none {
traverse_inline_body(cx, m.body);
}
}
}

View file

@ -8,8 +8,7 @@ import driver::session;
import session::session;
import syntax::{ast, ast_map};
import syntax::ast_util;
import syntax::ast_util::{is_local, local_def, split_class_items,
new_def_hash};
import syntax::ast_util::{is_local, local_def, new_def_hash};
import syntax::codemap::span;
import metadata::csearch;
import util::ppaux::{region_to_str, explain_region, vstore_to_str};
@ -3006,10 +3005,10 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
match cx.items.find(did.node) {
some(ast_map::node_item(i,_)) => {
match i.node {
ast::item_class(struct_def, _) => {
class_field_tys(struct_def.members)
}
_ => cx.sess.bug(~"class ID bound to non-class")
ast::item_class(struct_def, _) => {
class_field_tys(struct_def.fields)
}
_ => cx.sess.bug(~"class ID bound to non-class")
}
}
_ => {
@ -3062,9 +3061,9 @@ fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
some(ast_map::node_item(@{
node: item_class(struct_def, _), _
}, _)) => {
let (_,ms) = split_class_items(struct_def.members);
vec::map(ms, |m| {name: m.ident, id: m.id,
vis: m.vis})
vec::map(struct_def.methods, |m| {name: m.ident,
id: m.id,
vis: m.vis})
}
_ => {
cx.sess.bug(~"lookup_class_method_ids: id not bound to a class");
@ -3087,15 +3086,17 @@ fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
}
}
fn class_field_tys(items: ~[@class_member]) -> ~[field_ty] {
fn class_field_tys(fields: ~[@struct_field]) -> ~[field_ty] {
let mut rslt = ~[];
for items.each |it| {
match it.node {
instance_var(nm, _, cm, id, vis) => {
vec::push(rslt, {ident: nm, id: ast_util::local_def(id),
vis: vis, mutability: cm});
}
class_method(_) => ()
for fields.each |field| {
match field.node.kind {
named_field(ident, mutability, visibility) => {
vec::push(rslt, {ident: ident,
id: ast_util::local_def(field.node.id),
vis: visibility,
mutability: mutability});
}
unnamed_field => {}
}
}
rslt

View file

@ -43,8 +43,7 @@ import syntax::{ast, ast_util, ast_map};
import ast::spanned;
import ast::{required, provided};
import syntax::ast_map::node_id_to_str;
import syntax::ast_util::{local_def, respan, split_class_items,
split_trait_methods};
import syntax::ast_util::{local_def, respan, split_trait_methods};
import syntax::visit;
import metadata::csearch;
import driver::session::session;

View file

@ -372,19 +372,6 @@ fn check_method(ccx: @crate_ctxt, method: @ast::method,
check_bare_fn(ccx, method.decl, method.body, method.id, some(self_info));
}
fn check_class_member(ccx: @crate_ctxt, self_ty: ty::t,
node_id: ast::node_id,
cm: @ast::class_member) {
match cm.node {
ast::instance_var(_,t,_,_,_) => (),
ast::class_method(m) => {
let class_t = {self_ty: self_ty, node_id: node_id,
explicit_self: m.self_ty.node};
check_method(ccx, m, class_t)
}
}
}
fn check_no_duplicate_fields(tcx: ty::ctxt, fields:
~[(ast::ident, span)]) {
let field_names = hashmap::<@~str, span>(|x| str::hash(*x),
@ -435,13 +422,13 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def,
write_ty_to_tcx(tcx, dtor.node.self_id, class_t.self_ty);
};
// typecheck the members
for struct_def.members.each |m| {
check_class_member(ccx, self_ty, id, m);
// typecheck the methods
for struct_def.methods.each |m| {
check_method(ccx, m, {self_ty: self_ty, node_id: id,
explicit_self: m.self_ty.node});
}
// Check that there's at least one field
let (fields,_) = split_class_items(struct_def.members);
if fields.len() < 1u {
if struct_def.fields.len() < 1u {
ccx.tcx.sess.span_err(span, ~"a class must have at least one field");
}
// Check that the class is instantiable

View file

@ -17,7 +17,7 @@ import middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box};
import middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_is_var};
import middle::typeck::infer::{infer_ctxt, mk_subty};
import middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
import syntax::ast::{class_method, crate, def_id, def_mod, instance_var};
import syntax::ast::{crate, def_id, def_mod};
import syntax::ast::{item, item_class, item_const, item_enum, item_fn};
import syntax::ast::{item_foreign_mod, item_impl, item_mac, item_mod};
import syntax::ast::{item_trait, item_ty, local_crate, method, node_id};
@ -650,20 +650,13 @@ class CoherenceChecker {
id: node_id)
-> @Impl {
let mut methods = ~[];
for struct_def.members.each |class_member| {
match class_member.node {
instance_var(*) => {
// Nothing to do.
}
class_method(ast_method) => {
push(methods, @{
did: local_def(ast_method.id),
n_tps: ast_method.tps.len(),
ident: ast_method.ident,
self_type: ast_method.self_ty.node
});
}
}
for struct_def.methods.each |ast_method| {
push(methods, @{
did: local_def(ast_method.id),
n_tps: ast_method.tps.len(),
ident: ast_method.ident,
self_type: ast_method.self_ty.node
});
}
return @{ did: local_def(id), ident: ident, methods: methods };

View file

@ -215,10 +215,9 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) {
});
}
ast_map::node_item(@{node: ast::item_class(struct_def, _), _}, _) => {
let (_,ms) = split_class_items(struct_def.members);
// All methods need to be stored, since lookup_method
// relies on the same method cache for self-calls
store_methods::<@ast::method>(ccx, id, ms, |m| {
store_methods::<@ast::method>(ccx, id, struct_def.methods, |m| {
ty_of_method(ccx, m, rp)
});
}
@ -369,11 +368,12 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
fn convert_field(ccx: @crate_ctxt,
rp: bool,
bounds: @~[ty::param_bounds],
v: ast_util::ivar) {
let tt = ccx.to_ty(type_rscope(rp), v.ty);
write_ty_to_tcx(ccx.tcx, v.id, tt);
v: @ast::struct_field) {
let tt = ccx.to_ty(type_rscope(rp), v.node.ty);
write_ty_to_tcx(ccx.tcx, v.node.id, tt);
/* add the field to the tcache */
ccx.tcx.tcache.insert(local_def(v.id), {bounds: bounds, rp: rp, ty: tt});
ccx.tcx.tcache.insert(local_def(v.node.id),
{bounds: bounds, rp: rp, ty: tt});
}
type converted_method = {mty: ty::method, id: ast::node_id, span: span};
@ -505,13 +505,12 @@ fn convert_struct(ccx: @crate_ctxt, rp: bool, struct_def: @ast::struct_def,
ensure_trait_methods(ccx, id, tpt.ty);
// Write the type of each of the members
let (fields, methods) = split_class_items(struct_def.members);
for fields.each |f| {
for struct_def.fields.each |f| {
convert_field(ccx, rp, tpt.bounds, f);
}
let {bounds, substs} = mk_substs(ccx, tps, rp);
let selfty = ty::mk_class(tcx, local_def(id), substs);
let cms = convert_methods(ccx, methods, rp, bounds, selfty);
let cms = convert_methods(ccx, struct_def.methods, rp, bounds, selfty);
for struct_def.traits.each |trait_ref| {
check_methods_against_trait(ccx, tps, rp, selfty, trait_ref, cms);
// trait_ref.impl_id represents (class, trait) pair