parent
cf9a9d1ae8
commit
b5729bd600
11 changed files with 109 additions and 51 deletions
|
@ -657,6 +657,7 @@ type class_ctor = spanned<class_ctor_>;
|
|||
|
||||
#[auto_serialize]
|
||||
type class_ctor_ = {id: node_id,
|
||||
attrs: ~[attribute],
|
||||
self_id: node_id,
|
||||
dec: fn_decl,
|
||||
body: blk};
|
||||
|
@ -666,6 +667,7 @@ type class_dtor = spanned<class_dtor_>;
|
|||
|
||||
#[auto_serialize]
|
||||
type class_dtor_ = {id: node_id,
|
||||
attrs: ~[attribute],
|
||||
self_id: node_id,
|
||||
body: blk};
|
||||
|
||||
|
|
|
@ -126,8 +126,9 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
|
|||
cx.local_id += 1u;
|
||||
}
|
||||
alt fk {
|
||||
visit::fk_ctor(nm, tps, self_id, parent_id) {
|
||||
visit::fk_ctor(nm, attrs, tps, self_id, parent_id) {
|
||||
let ct = @{node: {id: id,
|
||||
attrs: attrs,
|
||||
self_id: self_id,
|
||||
dec: /* FIXME (#2543) */ copy decl,
|
||||
body: /* FIXME (#2543) */ copy body},
|
||||
|
@ -137,14 +138,13 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
|
|||
ct, parent_id,
|
||||
@/* FIXME (#2543) */ copy cx.path));
|
||||
}
|
||||
visit::fk_dtor(tps, self_id, parent_id) {
|
||||
let dt = @{node: {id: id, self_id: self_id,
|
||||
visit::fk_dtor(tps, attrs, self_id, parent_id) {
|
||||
let dt = @{node: {id: id, attrs: attrs, self_id: self_id,
|
||||
body: /* FIXME (#2543) */ copy body}, span: sp};
|
||||
cx.map.insert(id, node_dtor(/* FIXME (#2543) */ copy tps, dt,
|
||||
parent_id,
|
||||
@/* FIXME (#2543) */ copy cx.path));
|
||||
}
|
||||
|
||||
_ {}
|
||||
}
|
||||
visit::visit_fn(fk, decl, body, sp, id, cx, v);
|
||||
|
|
|
@ -464,13 +464,13 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
|
|||
vfn(id);
|
||||
|
||||
alt fk {
|
||||
visit::fk_ctor(nm, tps, self_id, parent_id) {
|
||||
visit::fk_ctor(nm, _, tps, self_id, parent_id) {
|
||||
vec::iter(tps, |tp| vfn(tp.id));
|
||||
vfn(id);
|
||||
vfn(self_id);
|
||||
vfn(parent_id.node);
|
||||
}
|
||||
visit::fk_dtor(tps, self_id, parent_id) {
|
||||
visit::fk_dtor(tps, _, self_id, parent_id) {
|
||||
vec::iter(tps, |tp| vfn(tp.id));
|
||||
vfn(id);
|
||||
vfn(self_id);
|
||||
|
|
|
@ -16,6 +16,7 @@ export wrap;
|
|||
export fold_ty_param;
|
||||
export fold_ty_params;
|
||||
export fold_fn_decl;
|
||||
export extensions;
|
||||
|
||||
iface ast_fold {
|
||||
fn fold_crate(crate) -> crate;
|
||||
|
@ -701,6 +702,12 @@ impl of ast_fold for ast_fold_precursor {
|
|||
}
|
||||
}
|
||||
|
||||
impl extensions for ast_fold {
|
||||
fn fold_attributes(attrs: ~[attribute]) -> ~[attribute] {
|
||||
attrs.map(|x| fold_attribute_(x, self))
|
||||
}
|
||||
}
|
||||
|
||||
fn make_fold(afp: ast_fold_precursor) -> ast_fold {
|
||||
afp as ast_fold
|
||||
}
|
||||
|
|
|
@ -96,8 +96,8 @@ enum pexpr {
|
|||
So that we can distinguish a class ctor or dtor
|
||||
from other class members
|
||||
*/
|
||||
enum class_contents { ctor_decl(fn_decl, blk, codemap::span),
|
||||
dtor_decl(blk, codemap::span),
|
||||
enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span),
|
||||
dtor_decl(blk, ~[attribute], codemap::span),
|
||||
members(~[@class_member]) }
|
||||
|
||||
type arg_or_capture_item = either<arg, capture_item>;
|
||||
|
@ -2145,31 +2145,34 @@ class parser {
|
|||
self.expect(token::LBRACE);
|
||||
let mut ms: ~[@class_member] = ~[];
|
||||
let ctor_id = self.get_id();
|
||||
let mut the_ctor : option<(fn_decl, blk, codemap::span)> = none;
|
||||
let mut the_dtor : option<(blk, codemap::span)> = none;
|
||||
let mut the_ctor : option<(fn_decl, ~[attribute], blk,
|
||||
codemap::span)> = none;
|
||||
let mut the_dtor : option<(blk, ~[attribute], codemap::span)> = none;
|
||||
while self.token != token::RBRACE {
|
||||
alt self.parse_class_item(class_path) {
|
||||
ctor_decl(a_fn_decl, blk, s) {
|
||||
the_ctor = some((a_fn_decl, blk, s));
|
||||
ctor_decl(a_fn_decl, attrs, blk, s) {
|
||||
the_ctor = some((a_fn_decl, attrs, blk, s));
|
||||
}
|
||||
dtor_decl(blk, s) {
|
||||
the_dtor = some((blk, s));
|
||||
dtor_decl(blk, attrs, s) {
|
||||
the_dtor = some((blk, attrs, s));
|
||||
}
|
||||
members(mms) { ms = vec::append(ms, mms); }
|
||||
}
|
||||
}
|
||||
let actual_dtor = do option::map(the_dtor) |dtor| {
|
||||
let (d_body, d_s) = dtor;
|
||||
let (d_body, d_attrs, d_s) = dtor;
|
||||
{node: {id: self.get_id(),
|
||||
attrs: d_attrs,
|
||||
self_id: self.get_id(),
|
||||
body: d_body},
|
||||
span: d_s}};
|
||||
self.bump();
|
||||
alt the_ctor {
|
||||
some((ct_d, ct_b, ct_s)) {
|
||||
some((ct_d, ct_attrs, ct_b, ct_s)) {
|
||||
(class_name,
|
||||
item_class(ty_params, traits, ms, {
|
||||
node: {id: ctor_id,
|
||||
attrs: ct_attrs,
|
||||
self_id: self.get_id(),
|
||||
dec: ct_d,
|
||||
body: ct_b},
|
||||
|
@ -2198,35 +2201,27 @@ class parser {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_ctor(result_ty: ast::ty_) -> class_contents {
|
||||
// FIXME (#2660): Can ctors/dtors have attrs?
|
||||
fn parse_ctor(attrs: ~[attribute],
|
||||
result_ty: ast::ty_) -> class_contents {
|
||||
let lo = self.last_span.lo;
|
||||
let (decl_, _) = self.parse_fn_decl(impure_fn, |p| p.parse_arg());
|
||||
let decl = {output: @{id: self.get_id(),
|
||||
node: result_ty, span: decl_.output.span}
|
||||
with decl_};
|
||||
let body = self.parse_block();
|
||||
ctor_decl(decl, body, mk_sp(lo, self.last_span.hi))
|
||||
ctor_decl(decl, attrs, body, mk_sp(lo, self.last_span.hi))
|
||||
}
|
||||
|
||||
fn parse_dtor() -> class_contents {
|
||||
// FIXME (#2660): Can ctors/dtors have attrs?
|
||||
fn parse_dtor(attrs: ~[attribute]) -> class_contents {
|
||||
let lo = self.last_span.lo;
|
||||
let body = self.parse_block();
|
||||
dtor_decl(body, mk_sp(lo, self.last_span.hi))
|
||||
dtor_decl(body, attrs, mk_sp(lo, self.last_span.hi))
|
||||
}
|
||||
|
||||
fn parse_class_item(class_name_with_tps: @path)
|
||||
-> class_contents {
|
||||
if self.eat_keyword(~"new") {
|
||||
// result type is always the type of the class
|
||||
ret self.parse_ctor(ty_path(class_name_with_tps,
|
||||
self.get_id()));
|
||||
}
|
||||
else if self.eat_keyword(~"drop") {
|
||||
ret self.parse_dtor();
|
||||
}
|
||||
else if self.eat_keyword(~"priv") {
|
||||
|
||||
if self.eat_keyword(~"priv") {
|
||||
self.expect(token::LBRACE);
|
||||
let mut results = ~[];
|
||||
while self.token != token::RBRACE {
|
||||
|
@ -2235,8 +2230,18 @@ class parser {
|
|||
self.bump();
|
||||
ret members(results);
|
||||
}
|
||||
|
||||
let attrs = self.parse_outer_attributes();
|
||||
|
||||
if self.eat_keyword(~"new") {
|
||||
// result type is always the type of the class
|
||||
ret self.parse_ctor(attrs, ty_path(class_name_with_tps,
|
||||
self.get_id()));
|
||||
}
|
||||
else if self.eat_keyword(~"drop") {
|
||||
ret self.parse_dtor(attrs);
|
||||
}
|
||||
else {
|
||||
// Probably need to parse attrs
|
||||
ret members(~[self.parse_single_class_item(public)]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ fn head(s: ps, w: ~str) {
|
|||
// outer-box is consistent
|
||||
cbox(s, indent_unit);
|
||||
// head-box is inconsistent
|
||||
ibox(s, str::len(w) + 1u);
|
||||
ibox(s, str::len(w) + 1);
|
||||
// keyword that starts the head
|
||||
word_nbsp(s, w);
|
||||
}
|
||||
|
@ -500,13 +500,19 @@ fn print_item(s: ps, &&item: @ast::item) {
|
|||
bopen(s);
|
||||
hardbreak_if_not_bol(s);
|
||||
maybe_print_comment(s, ctor.span.lo);
|
||||
head(s, ~"new");
|
||||
print_fn_args_and_ret(s, ctor.node.dec, ~[]);
|
||||
print_outer_attributes(s, ctor.node.attrs);
|
||||
/* Doesn't call head because there shouldn't be a space after new */
|
||||
cbox(s, indent_unit);
|
||||
ibox(s, 4);
|
||||
word(s.s, ~"new(");
|
||||
print_fn_args(s, ctor.node.dec, ~[]);
|
||||
word(s.s, ~")");
|
||||
space(s.s);
|
||||
print_block(s, ctor.node.body);
|
||||
do option::iter(m_dtor) |dtor| {
|
||||
hardbreak_if_not_bol(s);
|
||||
maybe_print_comment(s, dtor.span.lo);
|
||||
print_outer_attributes(s, dtor.node.attrs);
|
||||
head(s, ~"drop");
|
||||
print_block(s, dtor.node.body);
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ enum fn_kind {
|
|||
fk_method(ident, ~[ty_param], @method),
|
||||
fk_anon(proto, capture_clause), //< an anonymous function like fn@(...)
|
||||
fk_fn_block(capture_clause), //< a block {||...}
|
||||
fk_ctor(ident, ~[ty_param], node_id /* self id */,
|
||||
fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */,
|
||||
def_id /* parent class id */), // class constructor
|
||||
fk_dtor(~[ty_param], node_id /* self id */,
|
||||
fk_dtor(~[ty_param], ~[attribute], node_id /* self id */,
|
||||
def_id /* parent class id */) // class destructor
|
||||
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ enum fn_kind {
|
|||
fn name_of_fn(fk: fn_kind) -> ident {
|
||||
alt fk {
|
||||
fk_item_fn(name, _) | fk_method(name, _, _)
|
||||
| fk_ctor(name, _, _, _) { /* FIXME (#2543) */ copy name }
|
||||
| fk_ctor(name, _, _, _, _) { /* FIXME (#2543) */ copy name }
|
||||
fk_anon(*) | fk_fn_block(*) { @~"anon" }
|
||||
fk_dtor(*) { @~"drop" }
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ fn name_of_fn(fk: fn_kind) -> ident {
|
|||
fn tps_of_fn(fk: fn_kind) -> ~[ty_param] {
|
||||
alt fk {
|
||||
fk_item_fn(_, tps) | fk_method(_, tps, _)
|
||||
| fk_ctor(_, tps, _, _) | fk_dtor(tps, _, _) {
|
||||
| fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) {
|
||||
/* FIXME (#2543) */ copy tps
|
||||
}
|
||||
fk_anon(*) | fk_fn_block(*) { ~[] }
|
||||
|
@ -271,16 +271,17 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
|
|||
fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: ~[ty_param],
|
||||
parent_id: def_id, e: E, v: vt<E>) {
|
||||
v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm,
|
||||
ctor.node.attrs,
|
||||
/* FIXME (#2543) */ copy tps,
|
||||
ctor.node.self_id, parent_id), ctor.node.dec,
|
||||
ctor.node.body, ctor.span, ctor.node.id, e, v)
|
||||
ctor.node.self_id, parent_id),
|
||||
ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v)
|
||||
|
||||
}
|
||||
|
||||
fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: ~[ty_param],
|
||||
parent_id: def_id, e: E, v: vt<E>) {
|
||||
v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.self_id,
|
||||
parent_id), ast_util::dtor_dec(),
|
||||
v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs,
|
||||
dtor.node.self_id, parent_id), ast_util::dtor_dec(),
|
||||
dtor.node.body, dtor.span, dtor.node.id, e, v)
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import util::ppaux::ty_to_str;
|
|||
import dvec::extensions;
|
||||
import syntax::ast;
|
||||
import syntax::fold;
|
||||
import syntax::fold::*;
|
||||
import syntax::visit;
|
||||
import syntax::ast_map;
|
||||
import syntax::ast_util;
|
||||
|
@ -295,21 +296,25 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
|
|||
}
|
||||
ast::ii_ctor(ctor, nm, tps, parent_id) {
|
||||
let ctor_body = fld.fold_block(ctor.node.body);
|
||||
let ctor_attrs = fld.fold_attributes(ctor.node.attrs);
|
||||
let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld);
|
||||
let new_params = fold::fold_ty_params(tps, fld);
|
||||
let ctor_id = fld.new_id(ctor.node.id);
|
||||
let new_parent = xcx.tr_def_id(parent_id);
|
||||
ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl, id: ctor_id
|
||||
ast::ii_ctor({node: {body: ctor_body, attrs: ctor_attrs,
|
||||
dec: ctor_decl, id: ctor_id
|
||||
with ctor.node}
|
||||
with ctor}, nm, new_params, new_parent)
|
||||
}
|
||||
ast::ii_dtor(dtor, nm, tps, parent_id) {
|
||||
let dtor_body = fld.fold_block(dtor.node.body);
|
||||
let dtor_attrs = fld.fold_attributes(dtor.node.attrs);
|
||||
let new_params = fold::fold_ty_params(tps, fld);
|
||||
let dtor_id = fld.new_id(dtor.node.id);
|
||||
let new_parent = xcx.tr_def_id(parent_id);
|
||||
let new_self = fld.new_id(dtor.node.self_id);
|
||||
ast::ii_dtor({node: {id: dtor_id, self_id: new_self, body: dtor_body}
|
||||
ast::ii_dtor({node: {id: dtor_id, attrs: dtor_attrs,
|
||||
self_id: new_self, body: dtor_body}
|
||||
with dtor},
|
||||
nm, new_params, new_parent)
|
||||
}
|
||||
|
|
|
@ -111,10 +111,14 @@ fn traverse_public_item(cx: ctx, item: @item) {
|
|||
}
|
||||
item_class(tps, _traits, items, ctor, m_dtor) {
|
||||
cx.rmap.insert(ctor.node.id, ());
|
||||
if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs)
|
||||
!= attr::ia_none {
|
||||
traverse_inline_body(cx, ctor.node.body);
|
||||
}
|
||||
do option::iter(m_dtor) |dtor| {
|
||||
cx.rmap.insert(dtor.node.id, ());
|
||||
// dtors don't have attrs
|
||||
if tps.len() > 0u {
|
||||
if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs)
|
||||
!= attr::ia_none {
|
||||
traverse_inline_body(cx, dtor.node.body);
|
||||
}
|
||||
}
|
||||
|
|
11
src/test/run-pass/class-attributes-1.rs
Normal file
11
src/test/run-pass/class-attributes-1.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
// pp-exact - Make sure we actually print the attributes
|
||||
|
||||
class cat {
|
||||
#[cat_maker]
|
||||
new(name: ~str) { self.name = name; }
|
||||
#[cat_dropper]
|
||||
drop { #error["%s landed on hir feet", self.name]; }
|
||||
let name: ~str;
|
||||
}
|
||||
|
||||
fn main() { let _kitty = cat(~"Spotty"); }
|
17
src/test/run-pass/class-attributes-2.rs
Normal file
17
src/test/run-pass/class-attributes-2.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
class cat {
|
||||
let name: ~str;
|
||||
#[cat_maker]
|
||||
/**
|
||||
Maybe it should technically be a kitten_maker.
|
||||
*/
|
||||
new(name: ~str) { self.name = name; }
|
||||
#[cat_dropper]
|
||||
/**
|
||||
Actually, cats don't always land on their feet when you drop them.
|
||||
*/
|
||||
drop { #error("%s landed on hir feet", self.name); }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _kitty = cat(~"Spotty");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue