Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: Translate tuple struct constructors #3857

Merged
merged 1 commit into from
Oct 25, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1480,7 +1480,7 @@ type struct_def = {
dtor: Option<class_dtor>,
/* ID of the constructor. This is only used for tuple- or enum-like
* structs. */
ctor_id: node_id
ctor_id: Option<node_id>
};

/*
Expand Down
17 changes: 17 additions & 0 deletions src/libsyntax/ast_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ enum ast_node {
// Destructor for a class
node_dtor(~[ty_param], @class_dtor, def_id, @path),
node_block(blk),
node_struct_ctor(@struct_def, @item, @path)
}

type map = std::map::HashMap<node_id, ast_node>;
Expand Down Expand Up @@ -284,6 +285,19 @@ fn map_struct_def(struct_def: @ast::struct_def, parent_node: ast_node,
for vec::each(struct_def.methods) |m| {
map_method(d_id, p, *m, cx);
}
// If this is a tuple-like struct, register the constructor.
match struct_def.ctor_id {
None => {}
Some(ctor_id) => {
match parent_node {
node_item(item, _) => {
cx.map.insert(ctor_id,
node_struct_ctor(struct_def, item, p));
}
_ => fail ~"struct def parent wasn't an item"
}
}
}
}

fn map_view_item(vi: @view_item, cx: ctx, _v: vt) {
Expand Down Expand Up @@ -375,6 +389,9 @@ fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str {
Some(node_block(_)) => {
fmt!("block")
}
Some(node_struct_ctor(*)) => {
fmt!("struct_ctor")
}
}
}
// Local Variables:
Expand Down
6 changes: 6 additions & 0 deletions src/libsyntax/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,12 @@ fn view_path_id(p: @view_path) -> node_id {
}
}

/// Returns true if the given struct def is tuple-like; i.e. that its fields
/// are unnamed.
fn struct_def_is_tuple_like(struct_def: @ast::struct_def) -> bool {
struct_def.ctor_id.is_some()
}

// Local Variables:
// mode: rust
// fill-column: 78;
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)),
methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)),
dtor: dtor,
ctor_id: fld.new_id(struct_def.ctor_id)
ctor_id: option::map(&struct_def.ctor_id, |cid| fld.new_id(*cid))
};
}

Expand Down Expand Up @@ -565,7 +565,7 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ {
methods: vec::map(struct_def.methods,
|m| fld.fold_method(*m)),
dtor: dtor,
ctor_id: fld.new_id(struct_def.ctor_id)
ctor_id: option::map(&struct_def.ctor_id, |c| fld.new_id(*c))
})
}

Expand Down
9 changes: 7 additions & 2 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2659,9 +2659,11 @@ impl Parser {
let mut fields: ~[@struct_field];
let mut methods: ~[@method] = ~[];
let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None;
let is_tuple_like;

if self.eat(token::LBRACE) {
// It's a record-like struct.
is_tuple_like = false;
fields = ~[];
while self.token != token::RBRACE {
match self.parse_class_item() {
Expand Down Expand Up @@ -2694,6 +2696,7 @@ impl Parser {
self.bump();
} else if self.token == token::LPAREN {
// It's a tuple-like struct.
is_tuple_like = true;
fields = do self.parse_unspanned_seq(token::LPAREN, token::RPAREN,
seq_sep_trailing_allowed
(token::COMMA)) |p| {
Expand All @@ -2708,6 +2711,7 @@ impl Parser {
self.expect(token::SEMI);
} else if self.eat(token::SEMI) {
// It's a unit-like struct.
is_tuple_like = true;
fields = ~[];
} else {
self.fatal(fmt!("expected `{`, `(`, or `;` after struct name \
Expand All @@ -2723,13 +2727,14 @@ impl Parser {
body: d_body},
span: d_s}};
let _ = self.get_id(); // XXX: Workaround for crazy bug.
let new_id = self.get_id();
(class_name,
item_class(@{
traits: traits,
fields: move fields,
methods: move methods,
dtor: actual_dtor,
ctor_id: self.get_id()
ctor_id: if is_tuple_like { Some(new_id) } else { None }
}, ty_params),
None)
}
Expand Down Expand Up @@ -3076,7 +3081,7 @@ impl Parser {
fields: move fields,
methods: move methods,
dtor: actual_dtor,
ctor_id: self.get_id()
ctor_id: Some(self.get_id())
};
}

Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ mod special_idents {
const static : ident = ident { repr: 31u };
const intrinsic : ident = ident { repr: 32u };
const clownshoes_foreign_mod: ident = ident { repr: 33 };
const unnamed_field: ident = ident { repr: 34 };
}

struct ident_interner {
Expand Down
14 changes: 8 additions & 6 deletions src/rustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,12 +1187,14 @@ impl Resolver {

// If this struct is tuple-like or enum-like, define a name
// in the value namespace.
if struct_def.fields.len() == 0 ||
struct_def.fields[0].node.kind == unnamed_field {
name_bindings.define_value(
privacy,
def_class(local_def(struct_def.ctor_id)),
sp);
match struct_def.ctor_id {
None => {}
Some(ctor_id) => {
name_bindings.define_value(
privacy,
def_class(local_def(ctor_id)),
sp);
}
}

// Record the def ID of this struct.
Expand Down
91 changes: 83 additions & 8 deletions src/rustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,8 @@ fn trans_enum_variant(ccx: @crate_ctxt,
enum_id: ast::node_id,
variant: ast::variant,
args: ~[ast::variant_arg],
disr: int, is_degen: bool,
disr: int,
is_degen: bool,
param_substs: Option<param_substs>,
llfndecl: ValueRef) {
let _icx = ccx.insn_ctxt("trans_enum_variant");
Expand Down Expand Up @@ -1698,6 +1699,51 @@ fn trans_enum_variant(ccx: @crate_ctxt,
finish_fn(fcx, lltop);
}

// NB: In theory this should be merged with the function above. But the AST
// structures are completely different, so very little code would be shared.
fn trans_tuple_struct(ccx: @crate_ctxt,
fields: ~[@ast::struct_field],
ctor_id: ast::node_id,
param_substs: Option<param_substs>,
llfndecl: ValueRef) {
let _icx = ccx.insn_ctxt("trans_tuple_struct");

// Translate struct fields to function arguments.
let fn_args = do fields.map |field| {
{
mode: ast::expl(ast::by_copy),
ty: field.node.ty,
ident: special_idents::arg,
id: field.node.id
}
};

let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, ctor_id, None,
param_substs, None);
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);

let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
let arg_tys = ty::ty_fn_args(node_id_type(bcx, ctor_id));
let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys);

for fields.eachi |i, field| {
let lldestptr = GEPi(bcx, fcx.llretptr, [0, 0, i]);
let llarg = match fcx.llargs.get(field.node.id) {
local_mem(x) => x,
_ => {
ccx.tcx.sess.bug(~"trans_tuple_struct: llarg wasn't \
local_mem")
}
};
let arg_ty = arg_tys[i].ty;
memmove_ty(bcx, lldestptr, llarg, arg_ty);
}

build_return(bcx);
finish_fn(fcx, lltop);
}

fn trans_class_dtor(ccx: @crate_ctxt, path: path,
body: ast::blk, dtor_id: ast::node_id,
psubsts: Option<param_substs>,
Expand Down Expand Up @@ -1835,15 +1881,27 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def,
tps: ~[ast::ty_param], path: @ast_map::path,
ident: ast::ident, id: ast::node_id) {
// If there are type parameters, the destructor and constructor will be
// monomorphized, so we don't translate them here.
if tps.len() == 0u {
do option::iter(&struct_def.dtor) |dtor| {
trans_class_dtor(ccx, *path, dtor.node.body,
dtor.node.id, None, None, local_def(id));
};
// Translate the destructor.
do option::iter(&struct_def.dtor) |dtor| {
trans_class_dtor(ccx, *path, dtor.node.body,
dtor.node.id, None, None, local_def(id));
};

// If this is a tuple-like struct, translate the constructor.
match struct_def.ctor_id {
None => {}
Some(ctor_id) => {
let llfndecl = get_item_val(ccx, ctor_id);
trans_tuple_struct(ccx, struct_def.fields, ctor_id, None,
llfndecl);
}
}
}
// If there are ty params, the ctor will get monomorphized

// Translate methods
// Translate methods.
meth::trans_impl(ccx, *path, ident, struct_def.methods, tps, None, id);
}

Expand Down Expand Up @@ -2128,8 +2186,25 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
set_inline_hint(llfn);
llfn
}

ast_map::node_struct_ctor(struct_def, struct_item, struct_path) => {
// Only register the constructor if this is a tuple-like struct.
match struct_def.ctor_id {
None => {
ccx.tcx.sess.bug(~"attempt to register a constructor of \
a non-tuple-like struct")
}
Some(ctor_id) => {
let llfn = register_fn(ccx, struct_item.span,
*struct_path, ctor_id);
set_inline_hint(llfn);
llfn
}
}
}

_ => {
ccx.sess.bug(~"get_item_val(): unexpected variant");
ccx.sess.bug(~"get_item_val(): unexpected variant")
}
};
if !(exprt || ccx.reachable.contains_key(id)) {
Expand Down
5 changes: 4 additions & 1 deletion src/rustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ fn trans(bcx: block, expr: @ast::expr) -> Callee {
vid).args.len() > 0u;
fn_callee(bcx, trans_fn_ref(bcx, vid, ref_expr.id))
}
ast::def_class(def_id) => {
fn_callee(bcx, trans_fn_ref(bcx, def_id, ref_expr.id))
}
ast::def_arg(*) |
ast::def_local(*) |
ast::def_binding(*) |
Expand All @@ -99,7 +102,7 @@ fn trans(bcx: block, expr: @ast::expr) -> Callee {
}
ast::def_mod(*) | ast::def_foreign_mod(*) |
ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) |
ast::def_use(*) | ast::def_class(*) | ast::def_typaram_binder(*) |
ast::def_use(*) | ast::def_typaram_binder(*) |
ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) => {
bcx.tcx().sess.span_bug(
ref_expr.span,
Expand Down
13 changes: 13 additions & 0 deletions src/rustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ fn monomorphic_fn(ccx: @crate_ctxt,
ast_map::node_local(*) => {
ccx.tcx.sess.bug(~"Can't monomorphize a local")
}
ast_map::node_struct_ctor(_, i, pt) => (pt, i.ident, i.span)
};

// Look up the impl type if we're translating a default method.
Expand Down Expand Up @@ -208,6 +209,18 @@ fn monomorphic_fn(ccx: @crate_ctxt,
impl_did_opt.get());
d
}
ast_map::node_struct_ctor(struct_def, _, _) => {
let d = mk_lldecl();
set_inline_hint(d);
base::trans_tuple_struct(ccx,
struct_def.fields,
option::expect(struct_def.ctor_id,
~"ast-mapped tuple struct \
didn't have a ctor id"),
psubsts,
d);
d
}

// Ugh -- but this ensures any new variants won't be forgotten
ast_map::node_expr(*) |
Expand Down
12 changes: 11 additions & 1 deletion src/rustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3630,6 +3630,10 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
syntax::parse::token::special_idents::literally_dtor))
}

ast_map::node_struct_ctor(_, item, path) => {
vec::append_one(*path, ast_map::path_name(item.ident))
}

ast_map::node_stmt(*) | ast_map::node_expr(*) |
ast_map::node_arg(*) | ast_map::node_local(*) |
ast_map::node_export(*) | ast_map::node_block(*) => {
Expand Down Expand Up @@ -3874,7 +3878,13 @@ fn class_field_tys(fields: ~[@struct_field]) -> ~[field_ty] {
vis: visibility,
mutability: mutability});
}
unnamed_field => {}
unnamed_field => {
rslt.push({ident:
syntax::parse::token::special_idents::unnamed_field,
id: ast_util::local_def(field.node.id),
vis: ast::public,
mutability: ast::class_immutable});
}
}
}
rslt
Expand Down
Loading