Beginnings of front-end support for classes
Added class support to the parser, prettyprinter, fold, and visit. (See Issue 1726.) This is WIP -- the test case is xfailed, and attempting to compile it will error out in resolve.
This commit is contained in:
parent
d65eabd5de
commit
f3343b3571
10 changed files with 294 additions and 10 deletions
|
@ -119,6 +119,9 @@ fn encode_module_item_paths(ebml_w: ebml::writer, module: _mod, path: [str],
|
|||
encode_def_id(ebml_w, local_def(it.id));
|
||||
ebml::end_tag(ebml_w);
|
||||
}
|
||||
item_class(_,_,_,_) {
|
||||
fail "encode: implement item_class";
|
||||
}
|
||||
item_enum(variants, tps) {
|
||||
add_to_index(ebml_w, path, index, it.ident);
|
||||
ebml::start_tag(ebml_w, tag_paths_data_item);
|
||||
|
@ -340,6 +343,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||
ebml::end_tag(ebml_w);
|
||||
encode_enum_variant_info(ecx, ebml_w, item.id, variants, index, tps);
|
||||
}
|
||||
item_class(_,_,_,_) {
|
||||
fail "encode: implement item_class";
|
||||
}
|
||||
item_res(_, tps, _, _, ctor_id) {
|
||||
let fn_ty = node_id_to_type(tcx, ctor_id);
|
||||
|
||||
|
|
|
@ -1421,6 +1421,9 @@ fn index_mod(md: ast::_mod) -> mod_index {
|
|||
variant_idx += 1u;
|
||||
}
|
||||
}
|
||||
ast::item_class(_, items, ctor_decl, _) {
|
||||
fail "resolve::index_mod: item_class";
|
||||
}
|
||||
}
|
||||
}
|
||||
ret index;
|
||||
|
|
|
@ -60,6 +60,9 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
|
|||
ccx: ccx};
|
||||
find_pre_post_fn(fcx, body);
|
||||
}
|
||||
item_class(_,_,_,_) {
|
||||
fail "find_pre_post_item: implement item_class";
|
||||
}
|
||||
item_impl(_, _, _, ms) { for m in ms { find_pre_post_method(ccx, m); } }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -426,6 +426,9 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
|
|||
tcx.tcache.insert(local_def(it.id), tpt);
|
||||
ret tpt;
|
||||
}
|
||||
ast::item_class(_,_,_,_) {
|
||||
fail "ty_of_item: implement item_class";
|
||||
}
|
||||
ast::item_impl(_, _, _, _) | ast::item_mod(_) |
|
||||
ast::item_native_mod(_) { fail; }
|
||||
}
|
||||
|
@ -1232,7 +1235,7 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
|
|||
if subpats_len == 1u { "" } else { "s" },
|
||||
arg_len,
|
||||
if arg_len == 1u { "" } else { "s" }];
|
||||
tcx.sess.span_fatal(pat.span, s);
|
||||
tcx.sess.span_err(pat.span, s);
|
||||
}
|
||||
|
||||
vec::iter2(subpats, arg_types) {|subpat, arg_ty|
|
||||
|
@ -1240,7 +1243,7 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
|
|||
}
|
||||
} else if subpats_len > 0u {
|
||||
// TODO: note definition of enum variant
|
||||
tcx.sess.span_fatal
|
||||
tcx.sess.span_err
|
||||
(pat.span, #fmt["this pattern has %u field%s, \
|
||||
but the corresponding \
|
||||
variant has no fields",
|
||||
|
@ -1252,7 +1255,7 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
|
|||
_ {
|
||||
// FIXME: Switch expected and actual in this message? I
|
||||
// can never tell.
|
||||
tcx.sess.span_fatal
|
||||
tcx.sess.span_err
|
||||
(pat.span,
|
||||
#fmt["mismatched types: expected `%s` but found enum",
|
||||
ty_to_str(tcx, expected)]);
|
||||
|
|
|
@ -472,11 +472,29 @@ enum item_ {
|
|||
item_enum([variant], [ty_param]),
|
||||
item_res(fn_decl /* dtor */, [ty_param], blk,
|
||||
node_id /* dtor id */, node_id /* ctor id */),
|
||||
item_class([ty_param], /* ty params for class */
|
||||
[@class_item], /* methods, etc. */
|
||||
/* (not including ctor) */
|
||||
fn_decl, /* ctor decl */
|
||||
blk /* ctor body */
|
||||
),
|
||||
item_iface([ty_param], [ty_method]),
|
||||
item_impl([ty_param], option<@ty> /* iface */,
|
||||
@ty /* self */, [@method]),
|
||||
}
|
||||
|
||||
type class_item_ = {privacy: privacy, decl: @class_member};
|
||||
type class_item = spanned<class_item_>;
|
||||
|
||||
enum class_member {
|
||||
instance_var(ident, @ty, class_mutability, node_id),
|
||||
class_method(@item)
|
||||
}
|
||||
|
||||
enum class_mutability { class_mutable, class_immutable }
|
||||
|
||||
enum privacy { priv, pub }
|
||||
|
||||
type native_item =
|
||||
{ident: ident,
|
||||
attrs: [attribute],
|
||||
|
|
|
@ -27,6 +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_item_underscore: fn@(item_, ast_fold) -> item_,
|
||||
fold_method: fn@(&&@method, ast_fold) -> @method,
|
||||
fold_block: fn@(blk_, span, ast_fold) -> (blk_, span),
|
||||
|
@ -53,6 +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_item_underscore: fn@(item_) -> item_,
|
||||
fold_method: fn@(&&@method) -> @method,
|
||||
fold_block: fn@(blk) -> blk,
|
||||
|
@ -82,6 +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_item_underscore_dummy(_i: item_) -> item_ { fail; }
|
||||
fn nf_method_dummy(&&_m: @method) -> @method { fail; }
|
||||
fn nf_blk_dummy(_b: blk) -> blk { fail; }
|
||||
|
@ -220,6 +223,20 @@ fn noop_fold_item(&&i: @item, fld: ast_fold) -> @item {
|
|||
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)
|
||||
}
|
||||
class_method(i) { class_method(fld.fold_item(i)) }
|
||||
}},
|
||||
span: ci.span}
|
||||
}
|
||||
|
||||
fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
|
||||
ret alt i {
|
||||
item_const(t, e) { item_const(fld.fold_ty(t), fld.fold_expr(e)) }
|
||||
|
@ -233,6 +250,12 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
|
|||
item_enum(variants, typms) {
|
||||
item_enum(vec::map(variants, fld.fold_variant), typms)
|
||||
}
|
||||
item_class(typms, items, ctor_decl, ctor_body) {
|
||||
item_class(typms,
|
||||
vec::map(items, fld.fold_class_item),
|
||||
fold_fn_decl(ctor_decl, fld),
|
||||
fld.fold_block(ctor_body))
|
||||
}
|
||||
item_impl(tps, ifce, ty, methods) {
|
||||
item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty),
|
||||
vec::map(methods, fld.fold_method))
|
||||
|
@ -518,6 +541,7 @@ fn default_ast_fold() -> @ast_fold_precursor {
|
|||
fold_view_item: noop_fold_view_item,
|
||||
fold_native_item: noop_fold_native_item,
|
||||
fold_item: noop_fold_item,
|
||||
fold_class_item: noop_fold_class_item,
|
||||
fold_item_underscore: noop_fold_item_underscore,
|
||||
fold_method: noop_fold_method,
|
||||
fold_block: wrap(noop_fold_block),
|
||||
|
@ -548,6 +572,7 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
|
|||
fold_view_item: bind nf_view_item_dummy(_),
|
||||
fold_native_item: bind nf_native_item_dummy(_),
|
||||
fold_item: bind nf_item_dummy(_),
|
||||
fold_class_item: bind nf_class_item_dummy(_),
|
||||
fold_item_underscore: bind nf_item_underscore_dummy(_),
|
||||
fold_method: bind nf_method_dummy(_),
|
||||
fold_block: bind nf_blk_dummy(_),
|
||||
|
@ -591,6 +616,21 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
|
|||
fn f_item(afp: ast_fold_precursor, f: ast_fold, &&i: @item) -> @item {
|
||||
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) {
|
||||
instance_var(nm, f_ty(afp, f, t),
|
||||
mt, id)
|
||||
}
|
||||
class_method(i) {
|
||||
class_method(afp.fold_item(i, f))
|
||||
}
|
||||
}}, span: ci.span}
|
||||
}
|
||||
fn f_item_underscore(afp: ast_fold_precursor, f: ast_fold, i: item_) ->
|
||||
item_ {
|
||||
ret afp.fold_item_underscore(i, f);
|
||||
|
@ -665,6 +705,7 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
|
|||
fold_view_item: bind f_view_item(afp, result, _),
|
||||
fold_native_item: bind f_native_item(afp, result, _),
|
||||
fold_item: bind f_item(afp, result, _),
|
||||
fold_class_item: bind f_class_item(afp, result, _),
|
||||
fold_item_underscore: bind f_item_underscore(afp, result, _),
|
||||
fold_method: bind f_method(afp, result, _),
|
||||
fold_block: bind f_block(afp, result, _),
|
||||
|
|
|
@ -1616,6 +1616,21 @@ fn parse_let(p: parser) -> @ast::decl {
|
|||
ret @spanned(lo, p.last_span.hi, ast::decl_local(locals));
|
||||
}
|
||||
|
||||
fn parse_instance_var(p:parser) -> @ast::class_member {
|
||||
let is_mut = ast::class_immutable;
|
||||
expect_word(p, "let");
|
||||
if eat_word(p, "mutable") {
|
||||
is_mut = ast::class_mutable;
|
||||
}
|
||||
if !is_plain_ident(p) {
|
||||
p.fatal("expecting ident");
|
||||
}
|
||||
let name = parse_ident(p);
|
||||
expect(p, token::COLON);
|
||||
let ty = parse_ty(p, false);
|
||||
ret @ast::instance_var(name, ty, is_mut, p.get_id());
|
||||
}
|
||||
|
||||
fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
|
||||
fn check_expected_item(p: parser, current_attrs: [ast::attribute]) {
|
||||
// If we have attributes then we should have an item
|
||||
|
@ -1980,6 +1995,92 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
|||
attrs);
|
||||
}
|
||||
|
||||
fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||
let lo = p.last_span.lo;
|
||||
let class_name = parse_value_ident(p);
|
||||
let ty_params = parse_ty_params(p);
|
||||
expect(p, token::LBRACE);
|
||||
let items: [@ast::class_item] = [];
|
||||
let the_ctor : option<(ast::fn_decl, ast::blk)> = none;
|
||||
while p.token != token::RBRACE {
|
||||
alt parse_class_item(p) {
|
||||
ctor_decl(a_fn_decl, blk) {
|
||||
the_ctor = some((a_fn_decl, blk));
|
||||
}
|
||||
plain_decl(a_decl) {
|
||||
items += [@{node: {privacy: ast::pub, decl: a_decl},
|
||||
span: p.last_span}];
|
||||
}
|
||||
priv_decls(some_decls) {
|
||||
items += vec::map(some_decls, {|d|
|
||||
@{node: {privacy: ast::priv, decl: d},
|
||||
span: p.last_span}});
|
||||
}
|
||||
}
|
||||
}
|
||||
p.bump();
|
||||
alt the_ctor {
|
||||
some((ct_d, ct_b)) { ret mk_item(p, lo, p.last_span.hi, class_name,
|
||||
ast::item_class(ty_params, items, ct_d, ct_b), attrs); }
|
||||
/*
|
||||
Is it strange for the parser to check this?
|
||||
*/
|
||||
none { /* parse error */ fail "Class with no ctor"; }
|
||||
}
|
||||
}
|
||||
|
||||
// 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),
|
||||
// assumed to be public
|
||||
plain_decl(@ast::class_member),
|
||||
// contents of a priv section --
|
||||
// parse_class_item ensures that
|
||||
// none of these are a ctor decl
|
||||
priv_decls([@ast::class_member])}
|
||||
|
||||
fn parse_class_item(p:parser) -> class_contents {
|
||||
if eat_word(p, "new") {
|
||||
// Can ctors have attrs?
|
||||
let decl = parse_fn_decl(p, ast::impure_fn);
|
||||
let body = parse_block(p);
|
||||
ret ctor_decl(decl, body);
|
||||
}
|
||||
// TODO: refactor
|
||||
else if eat_word(p, "priv") {
|
||||
expect(p, token::LBRACE);
|
||||
let results = [];
|
||||
while p.token != token::RBRACE {
|
||||
alt parse_item(p, []) {
|
||||
some(i) {
|
||||
results += [@ast::class_method(i)];
|
||||
}
|
||||
_ {
|
||||
let a_var = parse_instance_var(p);
|
||||
expect(p, token::SEMI);
|
||||
results += [a_var];
|
||||
}
|
||||
}
|
||||
}
|
||||
p.bump();
|
||||
ret priv_decls(results);
|
||||
}
|
||||
else {
|
||||
// Probably need to parse attrs
|
||||
alt parse_item(p, []) {
|
||||
some(i) {
|
||||
ret plain_decl(@ast::class_method(i));
|
||||
}
|
||||
_ {
|
||||
let a_var = parse_instance_var(p);
|
||||
expect(p, token::SEMI);
|
||||
ret plain_decl(a_var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_mod_items(p: parser, term: token::token,
|
||||
first_item_attrs: [ast::attribute]) -> ast::_mod {
|
||||
// Shouldn't be any view items since we've already parsed an item attr
|
||||
|
@ -2222,7 +2323,10 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option<@ast::item> {
|
|||
ret some(parse_item_impl(p, attrs));
|
||||
} else if eat_word(p, "resource") {
|
||||
ret some(parse_item_res(p, attrs));
|
||||
} else { ret none; }
|
||||
} else if eat_word(p, "class") {
|
||||
ret some(parse_item_class(p, attrs));
|
||||
}
|
||||
else { ret none; }
|
||||
}
|
||||
|
||||
// A type to distingush between the parsing of item attributes or syntax
|
||||
|
|
|
@ -479,6 +479,52 @@ fn print_item(s: ps, &&item: @ast::item) {
|
|||
bclose(s, item.span);
|
||||
}
|
||||
}
|
||||
ast::item_class(tps,items,ctor_decl,ctor_body) {
|
||||
head(s, "class");
|
||||
word_nbsp(s, item.ident);
|
||||
print_type_params(s, tps);
|
||||
bopen(s);
|
||||
hardbreak_if_not_bol(s);
|
||||
head(s, "new");
|
||||
print_fn_args_and_ret(s, ctor_decl);
|
||||
space(s.s);
|
||||
print_block(s, ctor_body);
|
||||
for ci in items {
|
||||
/*
|
||||
TODO: collect all private items and print them
|
||||
in a single "priv" section
|
||||
*/
|
||||
hardbreak_if_not_bol(s);
|
||||
alt ci.node.privacy {
|
||||
ast::priv {
|
||||
head(s, "priv");
|
||||
bopen(s);
|
||||
hardbreak_if_not_bol(s);
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
alt *ci.node.decl {
|
||||
ast::instance_var(nm, t, mt, _) {
|
||||
word_nbsp(s, "let");
|
||||
alt mt {
|
||||
ast::class_mutable { word_nbsp(s, "mutable"); }
|
||||
_ {}
|
||||
}
|
||||
word(s.s, nm);
|
||||
word_nbsp(s, ":");
|
||||
print_type(s, t);
|
||||
word(s.s, ";");
|
||||
}
|
||||
ast::class_method(i) {
|
||||
print_item(s, i);
|
||||
}
|
||||
}
|
||||
alt ci.node.privacy {
|
||||
ast::priv { bclose(s, ci.span); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::item_impl(tps, ifce, ty, methods) {
|
||||
head(s, "impl");
|
||||
word(s.s, item.ident);
|
||||
|
@ -641,7 +687,6 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type,
|
|||
ast::unsafe_blk { word(s.s, "unsafe"); }
|
||||
ast::default_blk { }
|
||||
}
|
||||
|
||||
maybe_print_comment(s, blk.span.lo);
|
||||
let ann_node = node_block(s, blk);
|
||||
s.ann.pre(ann_node);
|
||||
|
|
|
@ -54,7 +54,8 @@ type visitor<E> =
|
|||
visit_ty: fn@(@ty, E, vt<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_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
|
||||
visit_class_item: fn@(span, privacy, @class_member, E, vt<E>)};
|
||||
|
||||
fn default_visitor<E>() -> visitor<E> {
|
||||
ret @{visit_mod: bind visit_mod::<E>(_, _, _, _, _),
|
||||
|
@ -71,7 +72,8 @@ fn default_visitor<E>() -> visitor<E> {
|
|||
visit_ty: bind skip_ty::<E>(_, _, _),
|
||||
visit_ty_params: bind visit_ty_params::<E>(_, _, _),
|
||||
visit_constr: bind visit_constr::<E>(_, _, _, _, _),
|
||||
visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _)};
|
||||
visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _),
|
||||
visit_class_item: bind visit_class_item::<E>(_,_,_,_,_)};
|
||||
}
|
||||
|
||||
fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
|
||||
|
@ -135,6 +137,14 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
|
|||
m.id, e, v);
|
||||
}
|
||||
}
|
||||
item_class(tps, members, ctor_decl, ctor_blk) {
|
||||
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);
|
||||
}
|
||||
visit_fn_decl(ctor_decl, e, v);
|
||||
v.visit_block(ctor_blk, e, v);
|
||||
}
|
||||
item_iface(tps, methods) {
|
||||
v.visit_ty_params(tps, e, v);
|
||||
for m in methods {
|
||||
|
@ -145,6 +155,18 @@ 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) {
|
||||
v.visit_ty(t, e, v);
|
||||
}
|
||||
class_method(i) {
|
||||
v.visit_item(i, e, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_ty<E>(_t: @ty, _e: E, _v: vt<E>) {}
|
||||
|
||||
fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
|
||||
|
@ -387,7 +409,8 @@ type simple_visitor =
|
|||
visit_ty: fn@(@ty),
|
||||
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_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
|
||||
visit_class_item: fn@(span, privacy, @class_member)};
|
||||
|
||||
fn simple_ignore_ty(_t: @ty) {}
|
||||
|
||||
|
@ -407,7 +430,8 @@ fn default_simple_visitor() -> simple_visitor {
|
|||
visit_ty_params: fn@(_ps: [ty_param]) {},
|
||||
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) { }
|
||||
_id: node_id) { },
|
||||
visit_class_item: fn@(_s: span, _p: privacy, _c: @class_member) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -482,6 +506,12 @@ 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: (),
|
||||
v: vt<()>) {
|
||||
f(s, p, cm);
|
||||
visit_class_item(s, p, cm, e, v);
|
||||
}
|
||||
ret mk_vt(@{visit_mod: bind v_mod(v.visit_mod, _, _, _, _, _),
|
||||
visit_view_item: bind v_view_item(v.visit_view_item, _, _, _),
|
||||
visit_native_item:
|
||||
|
@ -497,7 +527,9 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
|
|||
visit_ty: visit_ty,
|
||||
visit_ty_params: bind v_ty_params(v.visit_ty_params, _, _, _),
|
||||
visit_constr: bind v_constr(v.visit_constr, _, _, _, _, _),
|
||||
visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _)
|
||||
visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _),
|
||||
visit_class_item: bind v_class_item(v.visit_class_item, _, _,
|
||||
_, _, _)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
29
src/test/run-pass/classes.rs
Normal file
29
src/test/run-pass/classes.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
// xfail-test
|
||||
class cat {
|
||||
priv {
|
||||
let mutable meows : uint;
|
||||
fn meow() {
|
||||
#error("Meow");
|
||||
meows += 1;
|
||||
if meows % 5 == 0 {
|
||||
how_hungry += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let how_hungry : int;
|
||||
|
||||
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
|
||||
|
||||
fn speak() { meow(); }
|
||||
|
||||
fn eat() {
|
||||
if how_hungry > 0 {
|
||||
#error("OM NOM NOM");
|
||||
how_hungry -= 2;
|
||||
}
|
||||
else {
|
||||
#error("Not hungry!");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue