First cut at dtors for classes

Classes with dtors should compile now. Haven't yet tested
whether they actually run correctly.

Beginnings of support for #2295, though that won't be done until
there's more test cases and resources are removed.
This commit is contained in:
Tim Chevalier 2012-05-14 14:13:32 -07:00
parent 89cd2f6bd0
commit 5428a22b95
20 changed files with 216 additions and 55 deletions

View file

@ -669,8 +669,10 @@ enum item_ {
item_class([ty_param], /* ty params for class */ item_class([ty_param], /* ty params for class */
[@iface_ref], /* ifaces this class implements */ [@iface_ref], /* ifaces this class implements */
[@class_member], /* methods, etc. */ [@class_member], /* methods, etc. */
/* (not including ctor) */ /* (not including ctor or dtor) */
class_ctor, class_ctor,
/* dtor is optional */
option<class_dtor>,
region_param region_param
), ),
item_iface([ty_param], region_param, [ty_method]), item_iface([ty_param], region_param, [ty_method]),
@ -699,6 +701,14 @@ type class_ctor_ = {id: node_id,
dec: fn_decl, dec: fn_decl,
body: blk}; body: blk};
#[auto_serialize]
type class_dtor = spanned<class_dtor_>;
#[auto_serialize]
type class_dtor_ = {id: node_id,
self_id: node_id,
body: blk};
#[auto_serialize] #[auto_serialize]
type native_item = type native_item =
{ident: ident, {ident: ident,

View file

@ -361,6 +361,12 @@ fn operator_prec(op: ast::binop) -> uint {
or { 1u } or { 1u }
} }
} }
fn dtor_dec() -> fn_decl {
{inputs: [], output: @{id: 0, node: ty_nil, span: dummy_sp()},
purity: impure_fn, cf: return_val, constraints: []}
}
// Local Variables: // Local Variables:
// mode: rust // mode: rust
// fill-column: 78; // fill-column: 78;

View file

@ -274,10 +274,16 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
fold_ty_params(typms, fld), fold_ty_params(typms, fld),
r) r)
} }
item_class(typms, ifaces, items, ctor, rp) { item_class(typms, ifaces, items, ctor, m_dtor, rp) {
let ctor_body = fld.fold_block(ctor.node.body); let ctor_body = fld.fold_block(ctor.node.body);
let ctor_decl = fold_fn_decl(ctor.node.dec, fld); let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
let ctor_id = fld.new_id(ctor.node.id); let ctor_id = fld.new_id(ctor.node.id);
let dtor = option::map(m_dtor) {|dtor|
let dtor_body = fld.fold_block(dtor.node.body);
let dtor_id = fld.new_id(dtor.node.id);
{node: {body: dtor_body,
id: dtor_id with dtor.node}
with dtor}};
item_class( item_class(
typms, typms,
vec::map(ifaces, {|p| fold_iface_ref(p, fld) }), vec::map(ifaces, {|p| fold_iface_ref(p, fld) }),
@ -285,8 +291,7 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
{node: {body: ctor_body, {node: {body: ctor_body,
dec: ctor_decl, dec: ctor_decl,
id: ctor_id with ctor.node} id: ctor_id with ctor.node}
with ctor}, with ctor}, dtor, rp)
rp)
} }
item_impl(tps, rp, ifce, ty, methods) { item_impl(tps, rp, ifce, ty, methods) {
item_impl(fold_ty_params(tps, fld), item_impl(fold_ty_params(tps, fld),

View file

@ -1940,14 +1940,24 @@ fn parse_item_class(p: parser) -> item_info {
let mut ms: [@class_member] = []; let mut ms: [@class_member] = [];
let ctor_id = p.get_id(); let ctor_id = p.get_id();
let mut the_ctor : option<(fn_decl, blk, codemap::span)> = none; let mut the_ctor : option<(fn_decl, blk, codemap::span)> = none;
let mut the_dtor : option<(blk, codemap::span)> = none;
while p.token != token::RBRACE { while p.token != token::RBRACE {
alt parse_class_item(p, class_path) { 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)); the_ctor = some((a_fn_decl, blk, s));
} }
members(mms) { ms += mms; } dtor_decl(blk, s) {
the_dtor = some((blk, s));
}
members(mms) { ms += mms; }
} }
} }
let actual_dtor = option::map(the_dtor) {|dtor|
let (d_body, d_s) = dtor;
{node: {id: p.get_id(),
self_id: p.get_id(),
body: d_body},
span: d_s}};
p.bump(); p.bump();
alt the_ctor { alt the_ctor {
some((ct_d, ct_b, ct_s)) { some((ct_d, ct_b, ct_s)) {
@ -1957,7 +1967,7 @@ fn parse_item_class(p: parser) -> item_info {
self_id: p.get_id(), self_id: p.get_id(),
dec: ct_d, dec: ct_d,
body: ct_b}, body: ct_b},
span: ct_s}, rp), span: ct_s}, actual_dtor, rp),
none) none)
} }
/* /*
@ -1982,24 +1992,41 @@ fn parse_single_class_item(p: parser, vis: visibility)
} }
} }
// lets us identify the constructor declaration at /*
// parse time So that we can distinguish a class ctor or dtor
from other class members
*/
enum class_contents { ctor_decl(fn_decl, blk, codemap::span), enum class_contents { ctor_decl(fn_decl, blk, codemap::span),
dtor_decl(blk, codemap::span),
members([@class_member]) } members([@class_member]) }
fn parse_ctor(p: parser, result_ty: ast::ty_) -> class_contents {
// Can ctors/dtors have attrs? FIXME
let lo = p.last_span.lo;
let (decl_, _) = parse_fn_decl(p, impure_fn, parse_arg);
let decl = {output: @{id: p.get_id(),
node: result_ty, span: decl_.output.span}
with decl_};
let body = parse_block(p);
ctor_decl(decl, body, mk_sp(lo, p.last_span.hi))
}
fn parse_dtor(p: parser) -> class_contents {
// Can ctors/dtors have attrs? FIXME
let lo = p.last_span.lo;
let body = parse_block(p);
dtor_decl(body, mk_sp(lo, p.last_span.hi))
}
fn parse_class_item(p:parser, class_name_with_tps: @path) fn parse_class_item(p:parser, class_name_with_tps: @path)
-> class_contents { -> class_contents {
if eat_keyword(p, "new") { if eat_keyword(p, "new") {
let lo = p.last_span.lo; // result type is always the type of the class
// Can ctors have attrs? ret parse_ctor(p, ty_path(class_name_with_tps,
// result type is always the type of the class p.get_id()));
let (decl_, _) = parse_fn_decl(p, impure_fn, parse_arg); }
let decl = {output: @{id: p.get_id(), else if eat_keyword(p, "drop") {
node: ty_path(class_name_with_tps, p.get_id()), ret parse_dtor(p);
span: decl_.output.span}
with decl_};
let body = parse_block(p);
ret ctor_decl(decl, body, mk_sp(lo, p.last_span.hi));
} }
else if eat_keyword(p, "priv") { else if eat_keyword(p, "priv") {
expect(p, token::LBRACE); expect(p, token::LBRACE);

View file

@ -261,7 +261,7 @@ fn restricted_keyword_table() -> hashmap<str, ()> {
"assert", "assert",
"be", "break", "be", "break",
"check", "claim", "class", "const", "cont", "copy", "crust", "check", "claim", "class", "const", "cont", "copy", "crust",
"do", "do", "drop",
"else", "enum", "export", "else", "enum", "export",
"fail", "false", "fn", "for", "fail", "false", "fn", "for",
"if", "iface", "impl", "import", "if", "iface", "impl", "import",

View file

@ -507,7 +507,7 @@ fn print_item(s: ps, &&item: @ast::item) {
bclose(s, item.span); bclose(s, item.span);
} }
} }
ast::item_class(tps,ifaces,items,ctor, rp) { ast::item_class(tps, ifaces, items, ctor, m_dtor, rp) {
head(s, "class"); head(s, "class");
word_nbsp(s, item.ident); word_nbsp(s, item.ident);
print_region_param(s, rp); print_region_param(s, rp);
@ -522,6 +522,11 @@ fn print_item(s: ps, &&item: @ast::item) {
print_fn_args_and_ret(s, ctor.node.dec, []); print_fn_args_and_ret(s, ctor.node.dec, []);
space(s.s); space(s.s);
print_block(s, ctor.node.body); print_block(s, ctor.node.body);
option::iter(m_dtor) {|dtor|
hardbreak_if_not_bol(s);
head(s, "drop");
print_block(s, dtor.node.body);
}
for items.each {|ci| for items.each {|ci|
/* /*
FIXME: collect all private items and print them FIXME: collect all private items and print them

View file

@ -19,7 +19,10 @@ enum fn_kind {
fk_anon(proto, capture_clause), //< an anonymous function like fn@(...) fk_anon(proto, capture_clause), //< an anonymous function like fn@(...)
fk_fn_block(capture_clause), //< a block {||...} fk_fn_block(capture_clause), //< a block {||...}
fk_ctor(ident, [ty_param], node_id /* self id */, fk_ctor(ident, [ty_param], node_id /* self id */,
def_id /* parent class id */) // class constructor def_id /* parent class id */), // class constructor
fk_dtor([ty_param], node_id /* self id */,
def_id /* parent class id */) // class destructor
} }
fn name_of_fn(fk: fn_kind) -> ident { fn name_of_fn(fk: fn_kind) -> ident {
@ -27,13 +30,14 @@ fn name_of_fn(fk: fn_kind) -> ident {
fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _, _) fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _, _)
| fk_ctor(name, _, _, _) { name } | fk_ctor(name, _, _, _) { name }
fk_anon(*) | fk_fn_block(*) { "anon" } fk_anon(*) | fk_fn_block(*) { "anon" }
fk_dtor(*) { "drop" }
} }
} }
fn tps_of_fn(fk: fn_kind) -> [ty_param] { fn tps_of_fn(fk: fn_kind) -> [ty_param] {
alt fk { alt fk {
fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps, _) fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps, _)
| fk_ctor(_, tps, _, _) { tps } | fk_ctor(_, tps, _, _) | fk_dtor(tps, _, _) { tps }
fk_anon(*) | fk_fn_block(*) { [] } fk_anon(*) | fk_fn_block(*) { [] }
} }
} }
@ -140,7 +144,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
visit_method_helper(m, e, v) visit_method_helper(m, e, v)
} }
} }
item_class(tps, ifaces, members, ctor, _) { item_class(tps, ifaces, members, ctor, m_dtor, _) {
v.visit_ty_params(tps, e, v); v.visit_ty_params(tps, e, v);
for members.each {|m| for members.each {|m|
v.visit_class_item(m, e, v); v.visit_class_item(m, e, v);
@ -148,6 +152,9 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
for ifaces.each {|p| visit_path(p.path, e, v); } for ifaces.each {|p| visit_path(p.path, e, v); }
visit_class_ctor_helper(ctor, i.ident, tps, visit_class_ctor_helper(ctor, i.ident, tps,
ast_util::local_def(i.id), e, v); ast_util::local_def(i.id), e, v);
option::iter(m_dtor) {|dtor|
visit_class_dtor_helper(dtor, tps,
ast_util::local_def(i.id), e, v)};
} }
item_iface(tps, _rp, methods) { item_iface(tps, _rp, methods) {
v.visit_ty_params(tps, e, v); v.visit_ty_params(tps, e, v);
@ -280,12 +287,20 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
// Similar logic to the comment on visit_method_helper - Tim // Similar logic to the comment on visit_method_helper - Tim
fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: [ty_param], fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: [ty_param],
parent_id: def_id, e: E, v: vt<E>) { parent_id: def_id, e: E, v: vt<E>) {
v.visit_fn(visit::fk_ctor(nm, tps, ctor.node.self_id, v.visit_fn(fk_ctor(nm, tps, ctor.node.self_id,
parent_id), ctor.node.dec, parent_id), ctor.node.dec,
ctor.node.body, ctor.span, ctor.node.id, e, v) 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(tps, dtor.node.self_id,
parent_id), ast_util::dtor_dec(),
dtor.node.body, dtor.span, dtor.node.id, e, v)
}
fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span, fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
_id: node_id, e: E, v: vt<E>) { _id: node_id, e: E, v: vt<E>) {
visit_fn_decl(decl, e, v); visit_fn_decl(decl, e, v);

View file

@ -214,6 +214,13 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
vfn(self_id); vfn(self_id);
vfn(parent_id.node); vfn(parent_id.node);
} }
// not sure if this should be here? FIXME
visit::fk_dtor(tps, self_id, parent_id) {
vec::iter(tps) {|tp| vfn(tp.id)}
vfn(id);
vfn(self_id);
vfn(parent_id.node);
}
visit::fk_item_fn(_, tps) | visit::fk_item_fn(_, tps) |
visit::fk_res(_, tps, _) { visit::fk_res(_, tps, _) {
vec::iter(tps) {|tp| vfn(tp.id)} vec::iter(tps) {|tp| vfn(tp.id)}

View file

@ -187,7 +187,8 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
encode_def_id(ebml_w, local_def(it.id)); encode_def_id(ebml_w, local_def(it.id));
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_class(_, _, items, ctor, _) { // FIXME: I don't *think* dtor needs to be serialized?
item_class(_, _, items, ctor, _dtor, _) {
add_to_index(ebml_w, path, index, it.ident); add_to_index(ebml_w, path, index, it.ident);
ebml_w.start_tag(tag_paths_data_item); ebml_w.start_tag(tag_paths_data_item);
encode_name(ebml_w, it.ident); encode_name(ebml_w, it.ident);
@ -621,7 +622,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_enum_variant_info(ecx, ebml_w, item.id, variants, encode_enum_variant_info(ecx, ebml_w, item.id, variants,
path, index, tps); path, index, tps);
} }
item_class(tps, ifaces, items, ctor, rp) { // FIXME: not sure if the dtor should be serialized
item_class(tps, ifaces, items, ctor, _dtor, rp) {
/* First, encode the fields and methods /* First, encode the fields and methods
These come first because we need to write them to make These come first because we need to write them to make
the index, and the index needs to be in the item for the the index, and the index needs to be in the item for the
@ -801,7 +803,8 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_info_for_item(ecx, ebml_w, i, index, *pt); encode_info_for_item(ecx, ebml_w, i, index, *pt);
/* encode ctor, then encode items */ /* encode ctor, then encode items */
alt i.node { alt i.node {
item_class(tps, _, _, ctor, _) { // FIXME: not doing anything with dtor
item_class(tps, _, _, ctor, _, _) {
/* this is assuming that ctors aren't inlined... /* this is assuming that ctors aren't inlined...
probably shouldn't assume that */ probably shouldn't assume that */
#debug("encoding info for ctor %s %d", i.ident, #debug("encoding info for ctor %s %d", i.ident,

View file

@ -47,6 +47,8 @@ enum ast_node {
node_local(uint), node_local(uint),
// Constructor for either a resource or a class // Constructor for either a resource or a class
node_ctor(ident, [ty_param], a_ctor, @path), node_ctor(ident, [ty_param], a_ctor, @path),
// Destructor for a class
node_dtor([ty_param], @class_dtor, def_id, @path),
node_block(blk), node_block(blk),
} }
@ -134,6 +136,12 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
cx.map.insert(id, node_ctor(nm, tps, class_ctor(ct, parent_id), cx.map.insert(id, node_ctor(nm, tps, class_ctor(ct, parent_id),
@cx.path)); @cx.path));
} }
visit::fk_dtor(tps, self_id, parent_id) {
let dt = @{node: {id: id, self_id: self_id, body: body},
span: sp};
cx.map.insert(id, node_dtor(tps, dt, parent_id, @cx.path));
}
_ {} _ {}
} }
visit::visit_fn(fk, decl, body, sp, id, cx, v); visit::visit_fn(fk, decl, body, sp, id, cx, v);
@ -204,7 +212,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path)); cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
} }
} }
item_class(tps, ifces, items, ctor, _) { item_class(tps, ifces, items, ctor, dtor, _) {
let (_, ms) = ast_util::split_class_items(items); let (_, ms) = ast_util::split_class_items(items);
// Map iface refs to their parent classes. This is // Map iface refs to their parent classes. This is
// so we can find the self_ty // so we can find the self_ty
@ -283,9 +291,12 @@ fn node_id_to_str(map: map, id: node_id) -> str {
some(node_local(_)) { // FIXME: add more info here some(node_local(_)) { // FIXME: add more info here
#fmt["local (id=%?)", id] #fmt["local (id=%?)", id]
} }
some(node_ctor(_, _, _, _)) { // FIXME: add more info here some(node_ctor(*)) { // FIXME: add more info here
#fmt["node_ctor (id=%?)", id] #fmt["node_ctor (id=%?)", id]
} }
some(node_dtor(*)) { // FIXME: add more info here
#fmt["node_dtor (id=%?)", id]
}
some(node_block(_)) { some(node_block(_)) {
#fmt["block"] #fmt["block"]
} }

View file

@ -133,7 +133,7 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
let cap_clause = alt fk { let cap_clause = alt fk {
visit::fk_anon(_, cc) | visit::fk_fn_block(cc) { cc } visit::fk_anon(_, cc) | visit::fk_fn_block(cc) { cc }
visit::fk_item_fn(*) | visit::fk_method(*) | visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_res(*) | visit::fk_ctor(*) { @[] } visit::fk_res(*) | visit::fk_ctor(*) | visit::fk_dtor(*) { @[] }
}; };
let captured_vars = (*cap_clause).map { |cap_item| let captured_vars = (*cap_clause).map { |cap_item|
let cap_def = cx.tcx.def_map.get(cap_item.id); let cap_def = cx.tcx.def_map.get(cap_item.id);

View file

@ -375,7 +375,7 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
let fn_cx = alt fk { let fn_cx = alt fk {
visit::fk_item_fn(*) | visit::fk_method(*) | visit::fk_res(*) | visit::fk_item_fn(*) | visit::fk_method(*) | visit::fk_res(*) |
visit::fk_ctor(*) { visit::fk_ctor(*) | visit::fk_dtor(*) {
// Top-level functions are a root scope. // Top-level functions are a root scope.
{parent: some(id), closure_parent: some(id) with cx} {parent: some(id), closure_parent: some(id) with cx}
} }

View file

@ -437,7 +437,7 @@ fn resolve_names(e: @env, c: @ast::crate) {
ast::item_impl(_, _, ifce, _, _) { ast::item_impl(_, _, ifce, _, _) {
ifce.iter {|p| resolve_iface_ref(p, sc, e);} ifce.iter {|p| resolve_iface_ref(p, sc, e);}
} }
ast::item_class(_, ifaces, _, _, _) { ast::item_class(_, ifaces, _, _, _, _) {
for ifaces.each {|p| for ifaces.each {|p|
resolve_iface_ref(p, sc, e); resolve_iface_ref(p, sc, e);
} }
@ -564,22 +564,31 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
v.visit_ty(m.decl.output, msc, v); v.visit_ty(m.decl.output, msc, v);
} }
} }
ast::item_class(tps, ifaces, members, ctor, _) { ast::item_class(tps, ifaces, members, ctor, m_dtor, _) {
visit::visit_ty_params(tps, sc, v); visit::visit_ty_params(tps, sc, v);
// Can maybe skip this now that we require self on class fields // Can maybe skip this now that we require self on class fields
let class_scope = cons(scope_item(i), @sc); let class_scope = cons(scope_item(i), @sc);
/* visit the constructor... */ /* visit the constructor... */
let ctor_scope = cons(scope_method(ctor.node.self_id, tps), let ctor_scope = cons(scope_method(ctor.node.self_id, tps),
@class_scope); @class_scope);
/* /* visit the iface refs in the class scope */
but, I should visit the ifaces refs in the class scope, no?
*/
for ifaces.each {|p| for ifaces.each {|p|
visit::visit_path(p.path, class_scope, v); visit::visit_path(p.path, class_scope, v);
} }
// FIXME: should be fk_ctor?
visit_fn_with_scope(e, visit::fk_item_fn(i.ident, tps), ctor.node.dec, visit_fn_with_scope(e, visit::fk_item_fn(i.ident, tps), ctor.node.dec,
ctor.node.body, ctor.span, ctor.node.id, ctor.node.body, ctor.span, ctor.node.id,
ctor_scope, v); ctor_scope, v);
option::iter(m_dtor) {|dtor|
let dtor_scope = cons(scope_method(dtor.node.self_id, tps),
@class_scope);
visit_fn_with_scope(e, visit::fk_dtor(tps, dtor.node.self_id,
local_def(i.id)),
ast_util::dtor_dec(),
dtor.node.body, dtor.span, dtor.node.id,
dtor_scope, v);
};
/* visit the items */ /* visit the items */
for members.each {|cm| for members.each {|cm|
alt cm.node { alt cm.node {
@ -625,7 +634,8 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
for decl.constraints.each {|c| resolve_constr(e, c, sc, v); } for decl.constraints.each {|c| resolve_constr(e, c, sc, v); }
let scope = alt fk { let scope = alt fk {
visit::fk_item_fn(_, tps) | visit::fk_res(_, tps, _) | visit::fk_item_fn(_, tps) | visit::fk_res(_, tps, _) |
visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps, _, _) { visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps, _, _) |
visit::fk_dtor(tps, _, _) {
scope_bare_fn(decl, id, tps) } scope_bare_fn(decl, id, tps) }
visit::fk_anon(ast::proto_bare, _) { visit::fk_anon(ast::proto_bare, _) {
scope_bare_fn(decl, id, []) } scope_bare_fn(decl, id, []) }
@ -1041,7 +1051,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace,
ast::item_native_mod(m) { ast::item_native_mod(m) {
ret lookup_in_local_native_mod(e, it.id, sp, name, ns); ret lookup_in_local_native_mod(e, it.id, sp, name, ns);
} }
ast::item_class(tps, _, members, ctor, _) { ast::item_class(tps, _, members, ctor, _, _) {
if ns == ns_type { if ns == ns_type {
ret lookup_in_ty_params(e, name, tps); ret lookup_in_ty_params(e, name, tps);
} }
@ -1633,7 +1643,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
variant_idx += 1u; variant_idx += 1u;
} }
} }
ast::item_class(tps, _, items, ctor, _) { ast::item_class(tps, _, items, ctor, _, _) {
// add the class name itself // add the class name itself
add_to_index(index, it.ident, mie_item(it)); add_to_index(index, it.ident, mie_item(it));
// add the constructor decl // add the constructor decl
@ -2236,7 +2246,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl],
})}]; })}];
} }
} }
ast::item_class(tps, ifces, items, _, _) { ast::item_class(tps, ifces, items, _, _, _) {
let (_, mthds) = ast_util::split_class_items(items); let (_, mthds) = ast_util::split_class_items(items);
let n_tps = tps.len(); let n_tps = tps.len();
vec::iter(ifces) {|p| vec::iter(ifces) {|p|

View file

@ -4443,6 +4443,15 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
finish_fn(fcx, lltop); finish_fn(fcx, lltop);
} }
fn trans_class_dtor(ccx: @crate_ctxt, path: path,
body: ast::blk, lldtor_decl: ValueRef,
dtor_id: ast::node_id,
parent_id: ast::def_id) {
let class_ty = ty::lookup_item_type(ccx.tcx, parent_id).ty;
trans_fn(ccx, path, ast_util::dtor_dec(),
body, lldtor_decl, impl_self(class_ty), none, dtor_id);
}
fn trans_item(ccx: @crate_ctxt, item: ast::item) { fn trans_item(ccx: @crate_ctxt, item: ast::item) {
let _icx = ccx.insn_ctxt("trans_item"); let _icx = ccx.insn_ctxt("trans_item");
let path = alt check ccx.tcx.items.get(item.id) { let path = alt check ccx.tcx.items.get(item.id) {
@ -4509,7 +4518,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}; };
native::trans_native_mod(ccx, native_mod, abi); native::trans_native_mod(ccx, native_mod, abi);
} }
ast::item_class(tps, _ifaces, items, ctor, _) { ast::item_class(tps, _ifaces, items, ctor, m_dtor, _) {
if tps.len() == 0u { if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps), let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
// FIXME: vtables have to get filled in depending // FIXME: vtables have to get filled in depending
@ -4519,6 +4528,11 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body, trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body,
get_item_val(ccx, ctor.node.id), psubsts, get_item_val(ccx, ctor.node.id), psubsts,
ctor.node.id, local_def(item.id), ctor.span); ctor.node.id, local_def(item.id), ctor.span);
option::iter(m_dtor) {|dtor|
trans_class_dtor(ccx, *path, dtor.node.body,
get_item_val(ccx, dtor.node.id),
dtor.node.id, local_def(item.id));
};
} }
// If there are ty params, the ctor will get monomorphized // If there are ty params, the ctor will get monomorphized
@ -4744,6 +4758,12 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
} }
} }
} }
ast_map::node_dtor(tps, dt, parent_id, pt) {
let my_path = *pt + [path_name("dtor")];
let t = ty::node_id_to_type(ccx.tcx, dt.node.id);
register_fn_full(ccx, dt.span, my_path, dt.node.id, t)
}
ast_map::node_variant(v, enm, pth) { ast_map::node_variant(v, enm, pth) {
assert v.node.args.len() != 0u; assert v.node.args.len() != 0u;
let pth = *pth + [path_name(enm.ident), path_name(v.node.name)]; let pth = *pth + [path_name(enm.ident), path_name(v.node.name)];

View file

@ -94,7 +94,7 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
method_from_methods(ms, name) method_from_methods(ms, name)
} }
ast_map::node_item(@{node: ast_map::node_item(@{node:
ast::item_class(_, _, items, _, _), _}, _) { ast::item_class(_, _, items, _, _, _), _}, _) {
let (_,ms) = split_class_items(items); let (_,ms) = split_class_items(items);
method_from_methods(ms, name) method_from_methods(ms, name)
} }

View file

@ -102,8 +102,11 @@ fn traverse_public_item(cx: ctx, item: @item) {
} }
} }
} }
item_class(tps, _ifaces, items, ctor, _) { item_class(tps, _ifaces, items, ctor, m_dtor, _) {
cx.rmap.insert(ctor.node.id, ()); cx.rmap.insert(ctor.node.id, ());
option::iter(m_dtor) {|dtor|
cx.rmap.insert(dtor.node.id, ());
}
for vec::each(items) {|item| for vec::each(items) {|item|
alt item.node { alt item.node {
class_method(m) { class_method(m) {

View file

@ -57,7 +57,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
ccx: ccx}; ccx: ccx};
find_pre_post_fn(fcx, body); find_pre_post_fn(fcx, body);
} }
item_class(_,_,_,_,_) { item_class(*) {
fail "find_pre_post_item: shouldn't be called on item_class"; fail "find_pre_post_item: shouldn't be called on item_class";
} }
item_impl(_, _, _, _, ms) { item_impl(_, _, _, _, ms) {

View file

@ -2326,7 +2326,7 @@ fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
_, _, some(@{id: id, _}), _, _), _}, _)) { _, _, some(@{id: id, _}), _, _), _}, _)) {
some(node_id_to_type(cx, id)) some(node_id_to_type(cx, id))
} }
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _, _), some(ast_map::node_item(@{node: ast::item_class(_, _, _, _, _, _),
_},_)) { _},_)) {
alt cx.def_map.find(id.node) { alt cx.def_map.find(id.node) {
some(def_ty(iface_id)) { some(def_ty(iface_id)) {
@ -2408,6 +2408,10 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
ast_map::node_ctor(nm, _, _, path) { ast_map::node_ctor(nm, _, _, path) {
*path + [ast_map::path_name(nm)] *path + [ast_map::path_name(nm)]
} }
ast_map::node_dtor(_, _, _, path) {
*path + [ast_map::path_name("dtor")]
}
ast_map::node_expr(_) | ast_map::node_arg(_, _) | ast_map::node_expr(_) | ast_map::node_arg(_, _) |
ast_map::node_local(_) | ast_map::node_export(_, _) | ast_map::node_local(_) | ast_map::node_export(_, _) |
@ -2527,7 +2531,7 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
alt cx.items.find(did.node) { alt cx.items.find(did.node) {
some(ast_map::node_item(i,_)) { some(ast_map::node_item(i,_)) {
alt i.node { alt i.node {
ast::item_class(_, _, items, _, _) { ast::item_class(_, _, items, _, _, _) {
class_field_tys(items) class_field_tys(items)
} }
_ { cx.sess.bug("class ID bound to non-class"); } _ { cx.sess.bug("class ID bound to non-class"); }
@ -2569,7 +2573,7 @@ pure fn is_public(f: field_ty) -> bool {
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id) fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
: is_local(did) -> [{name: ident, id: node_id, vis: visibility}] { : is_local(did) -> [{name: ident, id: node_id, vis: visibility}] {
alt cx.items.find(did.node) { alt cx.items.find(did.node) {
some(ast_map::node_item(@{node: item_class(_,_,items,_,_), _}, _)) { some(ast_map::node_item(@{node: item_class(_,_,items,_,_,_), _}, _)) {
let (_,ms) = split_class_items(items); let (_,ms) = split_class_items(items);
vec::map(ms, {|m| {name: m.ident, id: m.id, vec::map(ms, {|m| {name: m.ident, id: m.id,
vis: m.vis}}) vis: m.vis}})

View file

@ -926,7 +926,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
ret tpt; ret tpt;
} }
ast::item_class(tps, _, _, _, rp) { ast::item_class(tps, _, _, _, _, rp) {
let {bounds,substs} = mk_substs(ccx, tps, rp); let {bounds,substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_class(tcx, local_def(it.id), substs); let t = ty::mk_class(tcx, local_def(it.id), substs);
let tpt = {bounds: bounds, rp: rp, ty: t}; let tpt = {bounds: bounds, rp: rp, ty: t};
@ -1487,7 +1487,7 @@ mod collect {
ty_of_ty_method(ccx, m, rp) ty_of_ty_method(ccx, m, rp)
}; };
} }
ast_map::node_item(@{node: ast::item_class(_,_,its,_,rp), _}, _) { ast_map::node_item(@{node: ast::item_class(_,_,its,_,_,rp), _}, _) {
let (_,ms) = split_class_items(its); let (_,ms) = split_class_items(its);
// All methods need to be stored, since lookup_method // All methods need to be stored, since lookup_method
// relies on the same method cache for self-calls // relies on the same method cache for self-calls
@ -1654,7 +1654,7 @@ mod collect {
write_ty_to_tcx(tcx, it.id, tpt.ty); write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_iface_methods(ccx, it.id); ensure_iface_methods(ccx, it.id);
} }
ast::item_class(tps, ifaces, members, ctor, rp) { ast::item_class(tps, ifaces, members, ctor, m_dtor, rp) {
// Write the class type // Write the class type
let tpt = ty_of_item(ccx, it); let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty); write_ty_to_tcx(tcx, it.id, tpt.ty);
@ -1671,6 +1671,22 @@ mod collect {
{bounds: tpt.bounds, {bounds: tpt.bounds,
rp: ast::rp_none, rp: ast::rp_none,
ty: t_ctor}); ty: t_ctor});
option::iter(m_dtor) {|dtor|
// Write the dtor type
let t_dtor = ty::mk_fn(tcx,
// not sure about empty_rscope
// FIXME
ty_of_fn_decl(ccx,
empty_rscope,
ast::proto_any,
ast_util::dtor_dec(),
none));
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id),
{bounds: tpt.bounds,
rp: ast::rp_none,
ty: t_dtor});
};
ensure_iface_methods(ccx, it.id); ensure_iface_methods(ccx, it.id);
/* FIXME: check for proper public/privateness */ /* FIXME: check for proper public/privateness */
// Write the type of each of the members // Write the type of each of the members
@ -2441,7 +2457,7 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
raw_ty: fcx.ccx.to_ty(type_rscope(rp), st)} raw_ty: fcx.ccx.to_ty(type_rscope(rp), st)}
} }
some(ast_map::node_item(@{node: ast::item_class(ts, some(ast_map::node_item(@{node: ast::item_class(ts,
_,_,_,rp), id: class_id, _},_)) { _,_,_,_,rp), id: class_id, _},_)) {
/* If the impl is a class, the self ty is just the class ty /* If the impl is a class, the self ty is just the class ty
(doing a no-op subst for the ty params; in the next step, (doing a no-op subst for the ty params; in the next step,
we substitute in fresh vars for them) we substitute in fresh vars for them)
@ -4443,7 +4459,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
let self_ty = ccx.to_ty(type_rscope(rp), ty); let self_ty = ccx.to_ty(type_rscope(rp), ty);
for ms.each {|m| check_method(ccx, m, self_ty);} for ms.each {|m| check_method(ccx, m, self_ty);}
} }
ast::item_class(tps, ifaces, members, ctor, rp) { ast::item_class(tps, ifaces, members, ctor, m_dtor, rp) {
let cid = some(it.id), tcx = ccx.tcx; let cid = some(it.id), tcx = ccx.tcx;
let class_t = ty::node_id_to_type(tcx, it.id); let class_t = ty::node_id_to_type(tcx, it.id);
let members_info = class_types(ccx, members, rp); let members_info = class_types(ccx, members, rp);
@ -4458,6 +4474,14 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
// Write the ctor's self's type // Write the ctor's self's type
write_ty_to_tcx(tcx, ctor.node.self_id, class_t); write_ty_to_tcx(tcx, ctor.node.self_id, class_t);
option::iter(m_dtor) {|dtor|
// typecheck the dtor
check_bare_fn(class_ccx, ast_util::dtor_dec(),
dtor.node.body, dtor.node.id,
some(class_t));
// Write the dtor's self's type
write_ty_to_tcx(tcx, dtor.node.self_id, class_t);
};
// typecheck the members // typecheck the members
for members.each {|m| check_class_member(class_ccx, class_t, m); } for members.each {|m| check_class_member(class_ccx, class_t, m); }
} }

View file

@ -0,0 +1,11 @@
class cat {
let done : native fn(uint);
let meows : uint;
new(done: native fn(uint)) {
self.meows = 0u;
self.done = done;
}
drop { self.done(self.meows); }
}
fn main() {}