Skip to content

Commit f3343b3

Browse files
committed
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.
1 parent d65eabd commit f3343b3

File tree

10 files changed

+294
-10
lines changed

10 files changed

+294
-10
lines changed

src/comp/metadata/encoder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ fn encode_module_item_paths(ebml_w: ebml::writer, module: _mod, path: [str],
119119
encode_def_id(ebml_w, local_def(it.id));
120120
ebml::end_tag(ebml_w);
121121
}
122+
item_class(_,_,_,_) {
123+
fail "encode: implement item_class";
124+
}
122125
item_enum(variants, tps) {
123126
add_to_index(ebml_w, path, index, it.ident);
124127
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,
340343
ebml::end_tag(ebml_w);
341344
encode_enum_variant_info(ecx, ebml_w, item.id, variants, index, tps);
342345
}
346+
item_class(_,_,_,_) {
347+
fail "encode: implement item_class";
348+
}
343349
item_res(_, tps, _, _, ctor_id) {
344350
let fn_ty = node_id_to_type(tcx, ctor_id);
345351

src/comp/middle/resolve.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,9 @@ fn index_mod(md: ast::_mod) -> mod_index {
14211421
variant_idx += 1u;
14221422
}
14231423
}
1424+
ast::item_class(_, items, ctor_decl, _) {
1425+
fail "resolve::index_mod: item_class";
1426+
}
14241427
}
14251428
}
14261429
ret index;

src/comp/middle/tstate/pre_post_conditions.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
6060
ccx: ccx};
6161
find_pre_post_fn(fcx, body);
6262
}
63+
item_class(_,_,_,_) {
64+
fail "find_pre_post_item: implement item_class";
65+
}
6366
item_impl(_, _, _, ms) { for m in ms { find_pre_post_method(ccx, m); } }
6467
}
6568
}

src/comp/middle/typeck.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,9 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
426426
tcx.tcache.insert(local_def(it.id), tpt);
427427
ret tpt;
428428
}
429+
ast::item_class(_,_,_,_) {
430+
fail "ty_of_item: implement item_class";
431+
}
429432
ast::item_impl(_, _, _, _) | ast::item_mod(_) |
430433
ast::item_native_mod(_) { fail; }
431434
}
@@ -1232,15 +1235,15 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
12321235
if subpats_len == 1u { "" } else { "s" },
12331236
arg_len,
12341237
if arg_len == 1u { "" } else { "s" }];
1235-
tcx.sess.span_fatal(pat.span, s);
1238+
tcx.sess.span_err(pat.span, s);
12361239
}
12371240

12381241
vec::iter2(subpats, arg_types) {|subpat, arg_ty|
12391242
check_pat(fcx, map, subpat, arg_ty);
12401243
}
12411244
} else if subpats_len > 0u {
12421245
// TODO: note definition of enum variant
1243-
tcx.sess.span_fatal
1246+
tcx.sess.span_err
12441247
(pat.span, #fmt["this pattern has %u field%s, \
12451248
but the corresponding \
12461249
variant has no fields",
@@ -1252,7 +1255,7 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
12521255
_ {
12531256
// FIXME: Switch expected and actual in this message? I
12541257
// can never tell.
1255-
tcx.sess.span_fatal
1258+
tcx.sess.span_err
12561259
(pat.span,
12571260
#fmt["mismatched types: expected `%s` but found enum",
12581261
ty_to_str(tcx, expected)]);

src/comp/syntax/ast.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,11 +472,29 @@ enum item_ {
472472
item_enum([variant], [ty_param]),
473473
item_res(fn_decl /* dtor */, [ty_param], blk,
474474
node_id /* dtor id */, node_id /* ctor id */),
475+
item_class([ty_param], /* ty params for class */
476+
[@class_item], /* methods, etc. */
477+
/* (not including ctor) */
478+
fn_decl, /* ctor decl */
479+
blk /* ctor body */
480+
),
475481
item_iface([ty_param], [ty_method]),
476482
item_impl([ty_param], option<@ty> /* iface */,
477483
@ty /* self */, [@method]),
478484
}
479485

486+
type class_item_ = {privacy: privacy, decl: @class_member};
487+
type class_item = spanned<class_item_>;
488+
489+
enum class_member {
490+
instance_var(ident, @ty, class_mutability, node_id),
491+
class_method(@item)
492+
}
493+
494+
enum class_mutability { class_mutable, class_immutable }
495+
496+
enum privacy { priv, pub }
497+
480498
type native_item =
481499
{ident: ident,
482500
attrs: [attribute],

src/comp/syntax/fold.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type ast_fold_precursor =
2727
fold_view_item: fn@(view_item_, ast_fold) -> view_item_,
2828
fold_native_item: fn@(&&@native_item, ast_fold) -> @native_item,
2929
fold_item: fn@(&&@item, ast_fold) -> @item,
30+
fold_class_item: fn@(&&@class_item, ast_fold) -> @class_item,
3031
fold_item_underscore: fn@(item_, ast_fold) -> item_,
3132
fold_method: fn@(&&@method, ast_fold) -> @method,
3233
fold_block: fn@(blk_, span, ast_fold) -> (blk_, span),
@@ -53,6 +54,7 @@ type a_f =
5354
fold_view_item: fn@(&&@view_item) -> @view_item,
5455
fold_native_item: fn@(&&@native_item) -> @native_item,
5556
fold_item: fn@(&&@item) -> @item,
57+
fold_class_item: fn@(&&@class_item) -> @class_item,
5658
fold_item_underscore: fn@(item_) -> item_,
5759
fold_method: fn@(&&@method) -> @method,
5860
fold_block: fn@(blk) -> blk,
@@ -82,6 +84,7 @@ fn nf_crate_directive_dummy(&&_c: @crate_directive) -> @crate_directive {
8284
fn nf_view_item_dummy(&&_v: @view_item) -> @view_item { fail; }
8385
fn nf_native_item_dummy(&&_n: @native_item) -> @native_item { fail; }
8486
fn nf_item_dummy(&&_i: @item) -> @item { fail; }
87+
fn nf_class_item_dummy(&&_ci: @class_item) -> @class_item { fail; }
8588
fn nf_item_underscore_dummy(_i: item_) -> item_ { fail; }
8689
fn nf_method_dummy(&&_m: @method) -> @method { fail; }
8790
fn nf_blk_dummy(_b: blk) -> blk { fail; }
@@ -220,6 +223,20 @@ fn noop_fold_item(&&i: @item, fld: ast_fold) -> @item {
220223
span: i.span};
221224
}
222225

226+
fn noop_fold_class_item(&&ci: @class_item, fld: ast_fold)
227+
-> @class_item {
228+
@{node: {
229+
privacy:ci.node.privacy,
230+
decl:
231+
@alt *ci.node.decl {
232+
instance_var(ident, t, cm, id) {
233+
instance_var(ident, fld.fold_ty(t), cm, id)
234+
}
235+
class_method(i) { class_method(fld.fold_item(i)) }
236+
}},
237+
span: ci.span}
238+
}
239+
223240
fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
224241
ret alt i {
225242
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_ {
233250
item_enum(variants, typms) {
234251
item_enum(vec::map(variants, fld.fold_variant), typms)
235252
}
253+
item_class(typms, items, ctor_decl, ctor_body) {
254+
item_class(typms,
255+
vec::map(items, fld.fold_class_item),
256+
fold_fn_decl(ctor_decl, fld),
257+
fld.fold_block(ctor_body))
258+
}
236259
item_impl(tps, ifce, ty, methods) {
237260
item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty),
238261
vec::map(methods, fld.fold_method))
@@ -518,6 +541,7 @@ fn default_ast_fold() -> @ast_fold_precursor {
518541
fold_view_item: noop_fold_view_item,
519542
fold_native_item: noop_fold_native_item,
520543
fold_item: noop_fold_item,
544+
fold_class_item: noop_fold_class_item,
521545
fold_item_underscore: noop_fold_item_underscore,
522546
fold_method: noop_fold_method,
523547
fold_block: wrap(noop_fold_block),
@@ -548,6 +572,7 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
548572
fold_view_item: bind nf_view_item_dummy(_),
549573
fold_native_item: bind nf_native_item_dummy(_),
550574
fold_item: bind nf_item_dummy(_),
575+
fold_class_item: bind nf_class_item_dummy(_),
551576
fold_item_underscore: bind nf_item_underscore_dummy(_),
552577
fold_method: bind nf_method_dummy(_),
553578
fold_block: bind nf_blk_dummy(_),
@@ -591,6 +616,21 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
591616
fn f_item(afp: ast_fold_precursor, f: ast_fold, &&i: @item) -> @item {
592617
ret afp.fold_item(i, f);
593618
}
619+
fn f_class_item(afp: ast_fold_precursor, f: ast_fold,
620+
&&ci: @class_item) -> @class_item {
621+
@{node:
622+
{privacy:ci.node.privacy,
623+
decl:
624+
@alt *ci.node.decl {
625+
instance_var(nm, t, mt, id) {
626+
instance_var(nm, f_ty(afp, f, t),
627+
mt, id)
628+
}
629+
class_method(i) {
630+
class_method(afp.fold_item(i, f))
631+
}
632+
}}, span: ci.span}
633+
}
594634
fn f_item_underscore(afp: ast_fold_precursor, f: ast_fold, i: item_) ->
595635
item_ {
596636
ret afp.fold_item_underscore(i, f);
@@ -665,6 +705,7 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
665705
fold_view_item: bind f_view_item(afp, result, _),
666706
fold_native_item: bind f_native_item(afp, result, _),
667707
fold_item: bind f_item(afp, result, _),
708+
fold_class_item: bind f_class_item(afp, result, _),
668709
fold_item_underscore: bind f_item_underscore(afp, result, _),
669710
fold_method: bind f_method(afp, result, _),
670711
fold_block: bind f_block(afp, result, _),

src/comp/syntax/parse/parser.rs

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,21 @@ fn parse_let(p: parser) -> @ast::decl {
16161616
ret @spanned(lo, p.last_span.hi, ast::decl_local(locals));
16171617
}
16181618

1619+
fn parse_instance_var(p:parser) -> @ast::class_member {
1620+
let is_mut = ast::class_immutable;
1621+
expect_word(p, "let");
1622+
if eat_word(p, "mutable") {
1623+
is_mut = ast::class_mutable;
1624+
}
1625+
if !is_plain_ident(p) {
1626+
p.fatal("expecting ident");
1627+
}
1628+
let name = parse_ident(p);
1629+
expect(p, token::COLON);
1630+
let ty = parse_ty(p, false);
1631+
ret @ast::instance_var(name, ty, is_mut, p.get_id());
1632+
}
1633+
16191634
fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
16201635
fn check_expected_item(p: parser, current_attrs: [ast::attribute]) {
16211636
// 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 {
19801995
attrs);
19811996
}
19821997

1998+
fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
1999+
let lo = p.last_span.lo;
2000+
let class_name = parse_value_ident(p);
2001+
let ty_params = parse_ty_params(p);
2002+
expect(p, token::LBRACE);
2003+
let items: [@ast::class_item] = [];
2004+
let the_ctor : option<(ast::fn_decl, ast::blk)> = none;
2005+
while p.token != token::RBRACE {
2006+
alt parse_class_item(p) {
2007+
ctor_decl(a_fn_decl, blk) {
2008+
the_ctor = some((a_fn_decl, blk));
2009+
}
2010+
plain_decl(a_decl) {
2011+
items += [@{node: {privacy: ast::pub, decl: a_decl},
2012+
span: p.last_span}];
2013+
}
2014+
priv_decls(some_decls) {
2015+
items += vec::map(some_decls, {|d|
2016+
@{node: {privacy: ast::priv, decl: d},
2017+
span: p.last_span}});
2018+
}
2019+
}
2020+
}
2021+
p.bump();
2022+
alt the_ctor {
2023+
some((ct_d, ct_b)) { ret mk_item(p, lo, p.last_span.hi, class_name,
2024+
ast::item_class(ty_params, items, ct_d, ct_b), attrs); }
2025+
/*
2026+
Is it strange for the parser to check this?
2027+
*/
2028+
none { /* parse error */ fail "Class with no ctor"; }
2029+
}
2030+
}
2031+
2032+
// lets us identify the constructor declaration at
2033+
// parse time
2034+
// we don't really want just the fn_decl...
2035+
enum class_contents { ctor_decl(ast::fn_decl, ast::blk),
2036+
// assumed to be public
2037+
plain_decl(@ast::class_member),
2038+
// contents of a priv section --
2039+
// parse_class_item ensures that
2040+
// none of these are a ctor decl
2041+
priv_decls([@ast::class_member])}
2042+
2043+
fn parse_class_item(p:parser) -> class_contents {
2044+
if eat_word(p, "new") {
2045+
// Can ctors have attrs?
2046+
let decl = parse_fn_decl(p, ast::impure_fn);
2047+
let body = parse_block(p);
2048+
ret ctor_decl(decl, body);
2049+
}
2050+
// TODO: refactor
2051+
else if eat_word(p, "priv") {
2052+
expect(p, token::LBRACE);
2053+
let results = [];
2054+
while p.token != token::RBRACE {
2055+
alt parse_item(p, []) {
2056+
some(i) {
2057+
results += [@ast::class_method(i)];
2058+
}
2059+
_ {
2060+
let a_var = parse_instance_var(p);
2061+
expect(p, token::SEMI);
2062+
results += [a_var];
2063+
}
2064+
}
2065+
}
2066+
p.bump();
2067+
ret priv_decls(results);
2068+
}
2069+
else {
2070+
// Probably need to parse attrs
2071+
alt parse_item(p, []) {
2072+
some(i) {
2073+
ret plain_decl(@ast::class_method(i));
2074+
}
2075+
_ {
2076+
let a_var = parse_instance_var(p);
2077+
expect(p, token::SEMI);
2078+
ret plain_decl(a_var);
2079+
}
2080+
}
2081+
}
2082+
}
2083+
19832084
fn parse_mod_items(p: parser, term: token::token,
19842085
first_item_attrs: [ast::attribute]) -> ast::_mod {
19852086
// 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> {
22222323
ret some(parse_item_impl(p, attrs));
22232324
} else if eat_word(p, "resource") {
22242325
ret some(parse_item_res(p, attrs));
2225-
} else { ret none; }
2326+
} else if eat_word(p, "class") {
2327+
ret some(parse_item_class(p, attrs));
2328+
}
2329+
else { ret none; }
22262330
}
22272331

22282332
// A type to distingush between the parsing of item attributes or syntax

src/comp/syntax/print/pprust.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,52 @@ fn print_item(s: ps, &&item: @ast::item) {
479479
bclose(s, item.span);
480480
}
481481
}
482+
ast::item_class(tps,items,ctor_decl,ctor_body) {
483+
head(s, "class");
484+
word_nbsp(s, item.ident);
485+
print_type_params(s, tps);
486+
bopen(s);
487+
hardbreak_if_not_bol(s);
488+
head(s, "new");
489+
print_fn_args_and_ret(s, ctor_decl);
490+
space(s.s);
491+
print_block(s, ctor_body);
492+
for ci in items {
493+
/*
494+
TODO: collect all private items and print them
495+
in a single "priv" section
496+
*/
497+
hardbreak_if_not_bol(s);
498+
alt ci.node.privacy {
499+
ast::priv {
500+
head(s, "priv");
501+
bopen(s);
502+
hardbreak_if_not_bol(s);
503+
}
504+
_ {}
505+
}
506+
alt *ci.node.decl {
507+
ast::instance_var(nm, t, mt, _) {
508+
word_nbsp(s, "let");
509+
alt mt {
510+
ast::class_mutable { word_nbsp(s, "mutable"); }
511+
_ {}
512+
}
513+
word(s.s, nm);
514+
word_nbsp(s, ":");
515+
print_type(s, t);
516+
word(s.s, ";");
517+
}
518+
ast::class_method(i) {
519+
print_item(s, i);
520+
}
521+
}
522+
alt ci.node.privacy {
523+
ast::priv { bclose(s, ci.span); }
524+
_ {}
525+
}
526+
}
527+
}
482528
ast::item_impl(tps, ifce, ty, methods) {
483529
head(s, "impl");
484530
word(s.s, item.ident);
@@ -641,7 +687,6 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type,
641687
ast::unsafe_blk { word(s.s, "unsafe"); }
642688
ast::default_blk { }
643689
}
644-
645690
maybe_print_comment(s, blk.span.lo);
646691
let ann_node = node_block(s, blk);
647692
s.ann.pre(ann_node);

0 commit comments

Comments
 (0)