Thread spans through the pipe compiler. They aren't perfect, but they make debugging far easier than core.rc:0:0.

Changed the is_bounded check, so we fail compiling core right now due to not supporting type parameters.
This commit is contained in:
Eric Holk 2012-07-24 16:58:48 -07:00
parent 7ecddb2771
commit 1dde5e7fc2
6 changed files with 91 additions and 71 deletions

View file

@ -8,7 +8,7 @@ import arc::methods;
// Things used by code generated by the pipe compiler.
export entangle, get_buffer, drop_buffer;
export send_packet_buffered, recv_packet_buffered;
export packet, mk_packet, entangle_buffer, has_buffer;
export packet, mk_packet, entangle_buffer, has_buffer, buffer_header;
// export these so we can find them in the buffer_resource
// destructor. This is probably another metadata bug.

View file

@ -19,30 +19,25 @@ fn ident(s: ~str) -> ast::ident {
@(copy s)
}
fn empty_span() -> span {
{lo: 0, hi: 0, expn_info: none}
}
fn span<T>(+x: T) -> ast::spanned<T> {
{node: x,
span: empty_span()}
}
fn path(id: ident) -> @ast::path {
@{span: empty_span(),
fn path(id: ident, span: span) -> @ast::path {
@{span: span,
global: false,
idents: ~[id],
rp: none,
types: ~[]}
}
fn empty_span() -> span {
{lo: 0, hi: 0, expn_info: none}
}
trait path_concat {
fn +(id: ident) -> @ast::path;
}
impl methods of path_concat for ident {
fn +(id: ident) -> @ast::path {
path(self) + id
path(self, empty_span()) + id
}
}
@ -107,19 +102,24 @@ trait ext_ctxt_ast_builder {
fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt;
fn stmt_expr(e: @ast::expr) -> @ast::stmt;
fn block_expr(b: ast::blk) -> @ast::expr;
fn empty_span() -> span;
}
impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
fn empty_span() -> span {
{lo: 0, hi: 0, expn_info: self.backtrace()}
}
fn block_expr(b: ast::blk) -> @ast::expr {
@{id: self.next_id(),
callee_id: self.next_id(),
node: ast::expr_block(b),
span: empty_span()}
span: self.empty_span()}
}
fn stmt_expr(e: @ast::expr) -> @ast::stmt {
@{node: ast::stmt_expr(e, self.next_id()),
span: empty_span()}
span: self.empty_span()}
}
fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt {
@ -133,43 +133,44 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
@{node: {is_mutbl: false,
ty: self.ty_infer(),
pat: @{id: self.next_id(),
node: ast::pat_ident(path(ident), none),
span: empty_span()},
node: ast::pat_ident(
path(ident, self.empty_span()), none),
span: self.empty_span()},
init: some({op: ast::init_move,
expr: e}),
id: self.next_id()},
span: empty_span()}]),
span: empty_span()}, self.next_id()),
span: empty_span()}
span: self.empty_span()}]),
span: self.empty_span()}, self.next_id()),
span: self.empty_span()}
}
fn field_imm(name: ident, e: @ast::expr) -> ast::field {
{node: {mutbl: ast::m_imm, ident: name, expr: e},
span: empty_span()}
span: self.empty_span()}
}
fn rec(+fields: ~[ast::field]) -> @ast::expr {
@{id: self.next_id(),
callee_id: self.next_id(),
node: ast::expr_rec(fields, none),
span: empty_span()}
span: self.empty_span()}
}
fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field {
{node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } },
span: empty_span()}
span: self.empty_span()}
}
fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::ty {
@{id: self.next_id(),
node: ast::ty_rec(fields),
span: empty_span()}
span: self.empty_span()}
}
fn ty_infer() -> @ast::ty {
@{id: self.next_id(),
node: ast::ty_infer,
span: empty_span()}
span: self.empty_span()}
}
fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound])
@ -201,7 +202,7 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
rules: ast::default_blk};
{node: blk,
span: empty_span()}
span: self.empty_span()}
}
fn expr_block(e: @ast::expr) -> ast::blk {
@ -223,7 +224,7 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
id: self.next_id(),
node: node,
vis: ast::public,
span: empty_span()}
span: self.empty_span()}
}
fn item_fn_poly(name: ident,
@ -261,12 +262,13 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
+tys: ~[@ast::ty]) -> ast::variant {
let args = tys.map(|ty| {ty: ty, id: self.next_id()});
span({name: name,
attrs: ~[],
args: args,
id: self.next_id(),
disr_expr: none,
vis: ast::public})
{node: {name: name,
attrs: ~[],
args: args,
id: self.next_id(),
disr_expr: none,
vis: ast::public},
span: self.empty_span()}
}
fn item_mod(name: ident,
@ -281,13 +283,13 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
// FIXME #2886: make sure the node ids are legal.
@{id: self.next_id(),
node: ast::ty_path(path, self.next_id()),
span: empty_span()}
span: self.empty_span()}
}
fn ty_nil_ast_builder() -> @ast::ty {
@{id: self.next_id(),
node: ast::ty_nil,
span: empty_span()}
span: self.empty_span()}
}
fn item_ty_poly(name: ident,
@ -301,6 +303,7 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
}
fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty] {
ty_params.map(|p| self.ty_path_ast_builder(path(p.ident)))
ty_params.map(|p| self.ty_path_ast_builder(
path(p.ident, self.empty_span())))
}
}

View file

@ -35,14 +35,14 @@ impl proto_check of proto::visitor<(), (), ()> for ext_ctxt {
fn visit_state(state: state, _m: &[()]) {
if state.messages.len() == 0 {
self.span_warn(
empty_span(), // use a real span!
state.span, // use a real span!
#fmt("state %s contains no messages, \
consider stepping to a terminal state instead",
*state.name))
}
}
fn visit_message(name: ident, _tys: &[@ast::ty],
fn visit_message(name: ident, _span: span, _tys: &[@ast::ty],
this: state, next: next_state) {
alt next {
some({state: next, tys: next_tys}) {
@ -51,7 +51,7 @@ impl proto_check of proto::visitor<(), (), ()> for ext_ctxt {
// This should be a span fatal, but then we need to
// track span information.
self.span_err(
empty_span(),
proto.get_state(next).span,
#fmt("message %s steps to undefined state, %s",
*name, *next));
}
@ -60,7 +60,7 @@ impl proto_check of proto::visitor<(), (), ()> for ext_ctxt {
if next.ty_params.len() != next_tys.len() {
self.span_err(
empty_span(), // use a real span
next.span, // use a real span
#fmt("message %s target (%s) \
needs %u type parameters, but got %u",
*name, *next.name,

View file

@ -13,7 +13,7 @@ trait proto_parser {
impl proto_parser of proto_parser for parser {
fn parse_proto(id: ident) -> protocol {
let proto = protocol(id);
let proto = protocol(id, self.span);
self.parse_seq_to_before_end(token::EOF,
{sep: none, trailing_sep_allowed: false},
@ -87,7 +87,7 @@ impl proto_parser of proto_parser for parser {
_ { self.fatal(~"invalid next state") }
};
state.add_message(mname, args, next);
state.add_message(mname, copy self.span, args, next);
}
}

View file

@ -49,7 +49,7 @@ impl compile of gen_send for message {
fn gen_send(cx: ext_ctxt) -> @ast::item {
#debug("pipec: gen_send");
alt self {
message(id, tys, this, some({state: next, tys: next_tys})) {
message(id, span, tys, this, some({state: next, tys: next_tys})) {
#debug("pipec: next state exists");
let next = this.proto.get_state(next);
assert next_tys.len() == next.ty_params.len();
@ -60,7 +60,7 @@ impl compile of gen_send for message {
);
let pipe_ty = cx.ty_path_ast_builder(
path(this.data_name())
path(this.data_name(), span)
.add_tys(cx.ty_vars(this.ty_params)));
let args_ast = vec::append(
~[cx.arg_mode(@~"pipe",
@ -110,13 +110,13 @@ impl compile of gen_send for message {
cx.item_fn_poly(self.name(),
args_ast,
cx.ty_path_ast_builder(path(next.data_name())
cx.ty_path_ast_builder(path(next.data_name(), span)
.add_tys(next_tys)),
self.get_params(),
cx.expr_block(body))
}
message(id, tys, this, none) {
message(id, span, tys, this, none) {
#debug("pipec: no next state");
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
@ -126,7 +126,8 @@ impl compile of gen_send for message {
let args_ast = vec::append(
~[cx.arg_mode(@~"pipe",
cx.ty_path_ast_builder(path(this.data_name())
cx.ty_path_ast_builder(path(this.data_name(),
span)
.add_tys(cx.ty_vars(this.ty_params))),
ast::by_copy)],
args_ast);
@ -158,7 +159,7 @@ impl compile of gen_send for message {
}
fn to_ty(cx: ext_ctxt) -> @ast::ty {
cx.ty_path_ast_builder(path(self.name())
cx.ty_path_ast_builder(path(self.name(), self.span())
.add_tys(cx.ty_vars(self.get_params())))
}
}
@ -177,7 +178,7 @@ impl compile of to_type_decls for state {
let mut items_msg = ~[];
for self.messages.each |m| {
let message(name, tys, this, next) = m;
let message(name, _span, tys, this, next) = m;
let tys = alt next {
some({state: next, tys: next_tys}) {
@ -287,7 +288,7 @@ impl compile of gen_init for protocol {
fn gen_buffer_init(ext_cx: ext_ctxt) -> @ast::expr {
ext_cx.rec(self.states.map_to_vec(|s| {
let fty = ext_cx.ty_path_ast_builder(path(s.name));
let fty = ext_cx.ty_path_ast_builder(path(s.name, s.span));
ext_cx.field_imm(s.name, #ast { pipes::mk_packet::<$(fty)>() })
}))
}
@ -324,7 +325,7 @@ impl compile of gen_init for protocol {
cx.ty_rec(
(copy self.states).map_to_vec(
|s| {
let ty = cx.ty_path_ast_builder(path(s.name));
let ty = cx.ty_path_ast_builder(path(s.name, s.span));
let fty = #ast[ty] {
pipes::packet<$(ty)>
};

View file

@ -30,23 +30,31 @@ impl methods for direction {
type next_state = option<{state: ident, tys: ~[@ast::ty]}>;
enum message {
// name, data, current state, next state
message(ident, ~[@ast::ty], state, next_state)
// name, span, data, current state, next state
message(ident, span, ~[@ast::ty], state, next_state)
}
impl methods for message {
fn name() -> ident {
alt self {
message(id, _, _, _) {
message(id, _, _, _, _) {
id
}
}
}
fn span() -> span {
alt self {
message(_, span, _, _, _) {
span
}
}
}
/// Return the type parameters actually used by this message
fn get_params() -> ~[ast::ty_param] {
alt self {
message(_, _, this, _) {
message(_, _, _, this, _) {
this.ty_params
}
}
@ -57,6 +65,7 @@ enum state {
state_(@{
id: uint,
name: ident,
span: span,
dir: direction,
ty_params: ~[ast::ty_param],
messages: dvec<message>,
@ -65,8 +74,9 @@ enum state {
}
impl methods for state {
fn add_message(name: ident, +data: ~[@ast::ty], next: next_state) {
self.messages.push(message(name, data, self,
fn add_message(name: ident, span: span,
+data: ~[@ast::ty], next: next_state) {
self.messages.push(message(name, span, data, self,
next));
}
@ -80,7 +90,7 @@ impl methods for state {
fn to_ty(cx: ext_ctxt) -> @ast::ty {
cx.ty_path_ast_builder
(path(self.name).add_tys(cx.ty_vars(self.ty_params)))
(path(self.name, self.span).add_tys(cx.ty_vars(self.ty_params)))
}
/// Iterate over the states that can be reached in one message
@ -88,7 +98,7 @@ impl methods for state {
fn reachable(f: fn(state) -> bool) {
for self.messages.each |m| {
alt m {
message(_, _, _, some({state: id, _})) {
message(_, _, _, _, some({state: id, _})) {
let state = self.proto.get_state(id);
if !f(state) { break }
}
@ -100,16 +110,20 @@ impl methods for state {
type protocol = @protocol_;
fn protocol(name: ident) -> protocol { @protocol_(name) }
fn protocol(name: ident, +span: span) -> protocol {
@protocol_(name, span)
}
class protocol_ {
let name: ident;
let span: span;
let states: dvec<state>;
let mut bounded: option<bool>;
new(name: ident) {
new(name: ident, span: span) {
self.name = name;
self.span = span;
self.states = dvec();
self.bounded = none;
}
@ -141,13 +155,14 @@ class protocol_ {
}
fn is_bounded() -> bool {
let bounded = self.bounded.get();
if bounded && self.has_ty_params() {
#debug("protocol %s has is bounded, but type parameters\
are not yet supported.",
*self.name);
false
}
else { bounded }
bounded
//if bounded && self.has_ty_params() {
// #debug("protocol %s has is bounded, but type parameters\
// are not yet supported.",
// *self.name);
// false
//}
//else { bounded }
}
}
@ -163,6 +178,7 @@ impl methods for protocol {
let state = state_(@{
id: self.states.len(),
name: name,
span: self.span,
dir: dir,
ty_params: ty_params,
messages: messages,
@ -177,7 +193,7 @@ impl methods for protocol {
trait visitor<Tproto, Tstate, Tmessage> {
fn visit_proto(proto: protocol, st: &[Tstate]) -> Tproto;
fn visit_state(state: state, m: &[Tmessage]) -> Tstate;
fn visit_message(name: ident, tys: &[@ast::ty],
fn visit_message(name: ident, spane: span, tys: &[@ast::ty],
this: state, next: next_state) -> Tmessage;
}
@ -187,8 +203,8 @@ fn visit<Tproto, Tstate, Tmessage, V: visitor<Tproto, Tstate, Tmessage>>(
// the copy keywords prevent recursive use of dvec
let states = do (copy proto.states).map_to_vec |s| {
let messages = do (copy s.messages).map_to_vec |m| {
let message(name, tys, this, next) = m;
visitor.visit_message(name, tys, this, next)
let message(name, span, tys, this, next) = m;
visitor.visit_message(name, span, tys, this, next)
};
visitor.visit_state(s, messages)
};