From e2fa6f03f5b3195b2f81e259a6b946567440b576 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Sat, 3 Mar 2012 17:49:23 -0800 Subject: Translate simple classes Programs using classes with fields only (no methods) compile and run, as long as nothing refers to a class in a different crate (todo). Also changed the AST representation of classes to have a separate record for constructor info (instead of inlining the fields in the item_class node), and fixed up spans and pretty-printing for classes. --- src/rustc/syntax/ast.rs | 12 +++++----- src/rustc/syntax/fold.rs | 12 +++++----- src/rustc/syntax/parse/parser.rs | 47 ++++++++++++++++++++++++---------------- src/rustc/syntax/print/pprust.rs | 9 +++++--- src/rustc/syntax/visit.rs | 6 ++--- 5 files changed, 50 insertions(+), 36 deletions(-) (limited to 'src/rustc/syntax') diff --git a/src/rustc/syntax/ast.rs b/src/rustc/syntax/ast.rs index eea47191eef..2f0c4bf7839 100644 --- a/src/rustc/syntax/ast.rs +++ b/src/rustc/syntax/ast.rs @@ -9,9 +9,6 @@ type ident = str; // Functions may or may not have names. type fn_ident = option; -// FIXME: with typestate constraint, could say -// idents and types are the same length, and are -// non-empty type path_ = {global: bool, idents: [ident], types: [@ty]}; type path = spanned; @@ -499,9 +496,7 @@ enum item_ { item_class([ty_param], /* ty params for class */ [@class_item], /* methods, etc. */ /* (not including ctor) */ - node_id, /* ctor id */ - fn_decl, /* ctor decl */ - blk /* ctor body */ + class_ctor ), item_iface([ty_param], [ty_method]), item_impl([ty_param], option<@ty> /* iface */, @@ -523,6 +518,11 @@ enum class_mutability { class_mutable, class_immutable } enum privacy { priv, pub } +type class_ctor = spanned; +type class_ctor_ = {id: node_id, + dec: fn_decl, + body: blk}; + type native_item = {ident: ident, attrs: [attribute], diff --git a/src/rustc/syntax/fold.rs b/src/rustc/syntax/fold.rs index 7ceae548769..d8088e39cb6 100644 --- a/src/rustc/syntax/fold.rs +++ b/src/rustc/syntax/fold.rs @@ -269,12 +269,14 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { item_enum(vec::map(variants, fld.fold_variant), fold_ty_params(typms, fld)) } - item_class(typms, items, id, ctor_decl, ctor_body) { - item_class(fold_ty_params(typms, fld), + item_class(typms, items, ctor) { + let ctor_body = fld.fold_block(ctor.node.body); + let ctor_decl = fold_fn_decl(ctor.node.dec, fld); + item_class(typms, vec::map(items, fld.fold_class_item), - id, - fold_fn_decl(ctor_decl, fld), - fld.fold_block(ctor_body)) + {node: {body: ctor_body, + dec: ctor_decl with ctor.node} + with ctor}) } item_impl(tps, ifce, ty, methods) { item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty), diff --git a/src/rustc/syntax/parse/parser.rs b/src/rustc/syntax/parse/parser.rs index 5837baf1ff9..e8df2f86305 100644 --- a/src/rustc/syntax/parse/parser.rs +++ b/src/rustc/syntax/parse/parser.rs @@ -1590,8 +1590,9 @@ 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 { +fn parse_instance_var(p:parser) -> (ast::class_member, codemap::span) { let is_mutbl = ast::class_immutable; + let lo = p.span.lo; expect_word(p, "let"); if eat_word(p, "mut") || eat_word(p, "mutable") { is_mutbl = ast::class_mutable; @@ -1602,7 +1603,8 @@ fn parse_instance_var(p:parser) -> ast::class_member { let name = parse_ident(p); expect(p, token::COLON); let ty = parse_ty(p, false); - ret ast::instance_var(name, ty, is_mutbl, p.get_id()); + ret (ast::instance_var(name, ty, is_mutbl, p.get_id()), + ast_util::mk_sp(lo, p.last_span.hi)); } fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt { @@ -1976,27 +1978,33 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item { expect(p, token::LBRACE); let items: [@ast::class_item] = []; let ctor_id = p.get_id(); - let the_ctor : option<(ast::fn_decl, ast::blk)> = none; + let the_ctor : option<(ast::fn_decl, ast::blk, codemap::span)> = none; while p.token != token::RBRACE { alt parse_class_item(p, class_path) { - ctor_decl(a_fn_decl, blk) { - the_ctor = some((a_fn_decl, blk)); + ctor_decl(a_fn_decl, blk, s) { + the_ctor = some((a_fn_decl, blk, s)); } - plain_decl(a_decl) { + plain_decl(a_decl, s) { items += [@{node: {privacy: ast::pub, decl: a_decl}, - span: p.last_span}]; + span: s}]; } priv_decls(some_decls) { - items += vec::map(some_decls, {|d| + items += vec::map(some_decls, {|p| + let (d, s) = p; @{node: {privacy: ast::priv, decl: d}, - span: p.last_span}}); + span: s}}); } } } 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, ctor_id, ct_d, ct_b), attrs); } + some((ct_d, ct_b, ct_s)) { ret mk_item(p, lo, p.last_span.hi, + class_name, + ast::item_class(ty_params, items, + {node: {id: ctor_id, + dec: ct_d, + body: ct_b}, + span: ct_s}), attrs); } /* Is it strange for the parser to check this? */ @@ -2007,16 +2015,17 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item { // 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), +enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span), // assumed to be public - plain_decl(ast::class_member), + plain_decl(ast::class_member, codemap::span), // contents of a priv section -- // parse_class_item ensures that // none of these are a ctor decl - priv_decls([ast::class_member])} + priv_decls([(ast::class_member, codemap::span)])} fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents { if eat_word(p, "new") { + let lo = p.last_span.lo; // Can ctors have attrs? // result type is always the type of the class let decl_ = parse_fn_decl(p, ast::impure_fn); @@ -2024,7 +2033,7 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk), span: decl_.output.span} with decl_}; let body = parse_block(p); - ret ctor_decl(decl, body); + ret ctor_decl(decl, body, ast_util::mk_sp(lo, p.last_span.hi)); } // FIXME: refactor else if eat_word(p, "priv") { @@ -2033,7 +2042,7 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk), while p.token != token::RBRACE { alt parse_item(p, []) { some(i) { - results += [ast::class_method(i)]; + results += [(ast::class_method(i), i.span)]; } _ { let a_var = parse_instance_var(p); @@ -2049,12 +2058,12 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk), // Probably need to parse attrs alt parse_item(p, []) { some(i) { - ret plain_decl(ast::class_method(i)); + ret plain_decl(ast::class_method(i), i.span); } _ { - let a_var = parse_instance_var(p); + let (a_var, a_span) = parse_instance_var(p); expect(p, token::SEMI); - ret plain_decl(a_var); + ret plain_decl(a_var, a_span); } } } diff --git a/src/rustc/syntax/print/pprust.rs b/src/rustc/syntax/print/pprust.rs index 5f92b5d5beb..d74d5d92c5f 100644 --- a/src/rustc/syntax/print/pprust.rs +++ b/src/rustc/syntax/print/pprust.rs @@ -471,22 +471,24 @@ fn print_item(s: ps, &&item: @ast::item) { bclose(s, item.span); } } - ast::item_class(tps,items,_,ctor_decl,ctor_body) { + ast::item_class(tps,items,ctor) { head(s, "class"); word_nbsp(s, item.ident); print_type_params(s, tps); bopen(s); hardbreak_if_not_bol(s); + maybe_print_comment(s, ctor.span.lo); head(s, "new"); - print_fn_args_and_ret(s, ctor_decl); + print_fn_args_and_ret(s, ctor.node.dec); space(s.s); - print_block(s, ctor_body); + print_block(s, ctor.node.body); for ci in items { /* FIXME: collect all private items and print them in a single "priv" section */ hardbreak_if_not_bol(s); + maybe_print_comment(s, ci.span.lo); alt ci.node.privacy { ast::priv { head(s, "priv"); @@ -516,6 +518,7 @@ fn print_item(s: ps, &&item: @ast::item) { _ {} } } + bclose(s, item.span); } ast::item_impl(tps, ifce, ty, methods) { head(s, "impl"); diff --git a/src/rustc/syntax/visit.rs b/src/rustc/syntax/visit.rs index 55958abd7af..dd1a53942fa 100644 --- a/src/rustc/syntax/visit.rs +++ b/src/rustc/syntax/visit.rs @@ -133,13 +133,13 @@ fn visit_item(i: @item, e: E, v: vt) { visit_method_helper(m, e, v) } } - item_class(tps, members, _, ctor_decl, ctor_blk) { + item_class(tps, members, ctor) { 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); + visit_fn_decl(ctor.node.dec, e, v); + v.visit_block(ctor.node.body, e, v); } item_iface(tps, methods) { v.visit_ty_params(tps, e, v); -- cgit 1.4.1-3-g733a5