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:
parent
7ecddb2771
commit
1dde5e7fc2
6 changed files with 91 additions and 71 deletions
|
@ -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.
|
||||
|
|
|
@ -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())))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)>
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue