2012-07-05 16:07:53 -07:00
|
|
|
// A protocol compiler for Rust.
|
|
|
|
|
2012-08-13 16:20:27 -07:00
|
|
|
import to_str::ToStr;
|
2012-07-05 16:07:53 -07:00
|
|
|
|
|
|
|
import dvec::dvec;
|
2012-07-16 17:27:04 -07:00
|
|
|
|
2012-07-05 16:07:53 -07:00
|
|
|
import ast::ident;
|
|
|
|
import util::interner;
|
|
|
|
import print::pprust;
|
|
|
|
import pprust::{item_to_str, ty_to_str};
|
|
|
|
import ext::base::{mk_ctxt, ext_ctxt};
|
|
|
|
import parse;
|
2012-07-05 18:01:11 -07:00
|
|
|
import parse::*;
|
2012-07-16 17:27:04 -07:00
|
|
|
import proto::*;
|
|
|
|
|
2012-07-11 15:00:40 -07:00
|
|
|
import ast_builder::append_types;
|
2012-07-05 16:07:53 -07:00
|
|
|
import ast_builder::path;
|
|
|
|
|
2012-07-23 18:50:53 -07:00
|
|
|
// Transitional reexports so qquote can find the paths it is looking for
|
|
|
|
mod syntax {
|
|
|
|
import ext;
|
|
|
|
export ext;
|
|
|
|
import parse;
|
|
|
|
export parse;
|
|
|
|
}
|
|
|
|
|
2012-07-17 16:49:54 -07:00
|
|
|
trait gen_send {
|
2012-08-07 11:46:52 -07:00
|
|
|
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item;
|
2012-07-17 16:49:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
trait to_type_decls {
|
|
|
|
fn to_type_decls(cx: ext_ctxt) -> ~[@ast::item];
|
|
|
|
fn to_endpoint_decls(cx: ext_ctxt, dir: direction) -> ~[@ast::item];
|
|
|
|
}
|
|
|
|
|
|
|
|
trait gen_init {
|
|
|
|
fn gen_init(cx: ext_ctxt) -> @ast::item;
|
|
|
|
fn compile(cx: ext_ctxt) -> @ast::item;
|
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl message: gen_send {
|
2012-08-07 11:46:52 -07:00
|
|
|
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item {
|
2012-07-30 16:01:07 -07:00
|
|
|
debug!{"pipec: gen_send"};
|
2012-08-06 12:34:08 -07:00
|
|
|
match self {
|
2012-08-03 19:59:04 -07:00
|
|
|
message(id, span, tys, this,
|
|
|
|
some({state: next, tys: next_tys})) => {
|
2012-08-07 11:46:52 -07:00
|
|
|
debug!("pipec: next state exists");
|
2012-07-05 18:01:11 -07:00
|
|
|
let next = this.proto.get_state(next);
|
|
|
|
assert next_tys.len() == next.ty_params.len();
|
2012-07-13 22:57:48 -07:00
|
|
|
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
|
2012-07-05 16:07:53 -07:00
|
|
|
|
|
|
|
let args_ast = (arg_names, tys).map(
|
|
|
|
|n, t| cx.arg_mode(n, t, ast::by_copy)
|
|
|
|
);
|
|
|
|
|
2012-07-20 19:06:32 -07:00
|
|
|
let pipe_ty = cx.ty_path_ast_builder(
|
2012-07-24 16:58:48 -07:00
|
|
|
path(this.data_name(), span)
|
2012-07-20 19:06:32 -07:00
|
|
|
.add_tys(cx.ty_vars(this.ty_params)));
|
2012-07-05 16:07:53 -07:00
|
|
|
let args_ast = vec::append(
|
2012-07-13 22:57:48 -07:00
|
|
|
~[cx.arg_mode(@~"pipe",
|
2012-07-20 19:06:32 -07:00
|
|
|
pipe_ty,
|
2012-07-05 16:07:53 -07:00
|
|
|
ast::by_copy)],
|
|
|
|
args_ast);
|
|
|
|
|
2012-07-23 18:50:53 -07:00
|
|
|
let mut body = ~"{\n";
|
|
|
|
|
|
|
|
if this.proto.is_bounded() {
|
2012-08-06 12:34:08 -07:00
|
|
|
let (sp, rp) = match (this.dir, next.dir) {
|
2012-08-03 19:59:04 -07:00
|
|
|
(send, send) => (~"c", ~"s"),
|
|
|
|
(send, recv) => (~"s", ~"c"),
|
|
|
|
(recv, send) => (~"s", ~"c"),
|
|
|
|
(recv, recv) => (~"c", ~"s")
|
2012-07-23 18:50:53 -07:00
|
|
|
};
|
2012-07-05 16:07:53 -07:00
|
|
|
|
2012-08-03 11:22:35 -07:00
|
|
|
body += ~"let b = pipe.reuse_buffer();\n";
|
2012-08-07 11:46:52 -07:00
|
|
|
body += fmt!("let %s = pipes::send_packet_buffered(\
|
2012-07-23 18:50:53 -07:00
|
|
|
ptr::addr_of(b.buffer.data.%s));\n",
|
2012-08-07 11:46:52 -07:00
|
|
|
sp, *next.name);
|
|
|
|
body += fmt!("let %s = pipes::recv_packet_buffered(\
|
2012-07-23 18:50:53 -07:00
|
|
|
ptr::addr_of(b.buffer.data.%s));\n",
|
2012-08-07 11:46:52 -07:00
|
|
|
rp, *next.name);
|
2012-07-23 18:50:53 -07:00
|
|
|
}
|
|
|
|
else {
|
2012-08-06 12:34:08 -07:00
|
|
|
let pat = match (this.dir, next.dir) {
|
2012-08-07 11:46:52 -07:00
|
|
|
(send, send) => "(c, s)",
|
|
|
|
(send, recv) => "(s, c)",
|
|
|
|
(recv, send) => "(s, c)",
|
|
|
|
(recv, recv) => "(c, s)"
|
2012-07-23 18:50:53 -07:00
|
|
|
};
|
|
|
|
|
2012-08-07 11:46:52 -07:00
|
|
|
body += fmt!("let %s = pipes::entangle();\n", pat);
|
2012-07-23 18:50:53 -07:00
|
|
|
}
|
2012-08-07 11:46:52 -07:00
|
|
|
body += fmt!("let message = %s::%s(%s);\n",
|
2012-07-05 16:07:53 -07:00
|
|
|
*this.proto.name,
|
|
|
|
*self.name(),
|
2012-07-13 22:57:48 -07:00
|
|
|
str::connect(vec::append_one(arg_names, @~"s")
|
2012-07-05 16:07:53 -07:00
|
|
|
.map(|x| *x),
|
2012-08-07 11:46:52 -07:00
|
|
|
~", "));
|
|
|
|
|
|
|
|
if !try {
|
|
|
|
body += fmt!{"pipes::send(pipe, message);\n"};
|
|
|
|
// return the new channel
|
|
|
|
body += ~"c }";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
body += fmt!("if pipes::send(pipe, message) {\n \
|
2012-08-15 16:22:40 -07:00
|
|
|
pipes::rt::make_some(c) \
|
|
|
|
} else { pipes::rt::make_none() } }");
|
2012-08-07 11:46:52 -07:00
|
|
|
}
|
2012-07-05 16:07:53 -07:00
|
|
|
|
|
|
|
let body = cx.parse_expr(body);
|
|
|
|
|
2012-08-07 11:46:52 -07:00
|
|
|
let mut rty = cx.ty_path_ast_builder(path(next.data_name(),
|
|
|
|
span)
|
|
|
|
.add_tys(next_tys));
|
|
|
|
if try {
|
|
|
|
rty = cx.ty_option(rty);
|
|
|
|
}
|
|
|
|
|
|
|
|
let name = if try {
|
|
|
|
@(~"try_" + *self.name())
|
|
|
|
}
|
|
|
|
else { self.name() };
|
|
|
|
|
|
|
|
cx.item_fn_poly(name,
|
2012-07-05 16:07:53 -07:00
|
|
|
args_ast,
|
2012-08-07 11:46:52 -07:00
|
|
|
rty,
|
2012-07-05 16:07:53 -07:00
|
|
|
self.get_params(),
|
|
|
|
cx.expr_block(body))
|
|
|
|
}
|
2012-07-16 14:44:27 -07:00
|
|
|
|
2012-08-07 11:46:52 -07:00
|
|
|
message(id, span, tys, this, none) => {
|
|
|
|
debug!{"pipec: no next state"};
|
|
|
|
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
|
|
|
|
|
|
|
|
let args_ast = (arg_names, tys).map(
|
|
|
|
|n, t| cx.arg_mode(n, t, ast::by_copy)
|
|
|
|
);
|
|
|
|
|
|
|
|
let args_ast = vec::append(
|
|
|
|
~[cx.arg_mode(@~"pipe",
|
|
|
|
cx.ty_path_ast_builder(
|
|
|
|
path(this.data_name(), span)
|
|
|
|
.add_tys(cx.ty_vars(this.ty_params))),
|
|
|
|
ast::by_copy)],
|
|
|
|
args_ast);
|
|
|
|
|
|
|
|
let message_args = if arg_names.len() == 0 {
|
|
|
|
~""
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
~"(" + str::connect(arg_names.map(|x| *x), ~", ") + ~")"
|
|
|
|
};
|
2012-07-16 14:44:27 -07:00
|
|
|
|
2012-08-07 11:46:52 -07:00
|
|
|
let mut body = ~"{ ";
|
|
|
|
body += fmt!{"let message = %s::%s%s;\n",
|
|
|
|
*this.proto.name,
|
|
|
|
*self.name(),
|
|
|
|
message_args};
|
|
|
|
|
|
|
|
if !try {
|
|
|
|
body += fmt!{"pipes::send(pipe, message);\n"};
|
|
|
|
body += ~" }";
|
|
|
|
} else {
|
|
|
|
body += fmt!("if pipes::send(pipe, message) { \
|
2012-08-15 16:22:40 -07:00
|
|
|
pipes::rt::make_some(()) \
|
|
|
|
} else { pipes::rt::make_none() } }");
|
2012-08-07 11:46:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let body = cx.parse_expr(body);
|
|
|
|
|
|
|
|
let name = if try {
|
|
|
|
@(~"try_" + *self.name())
|
|
|
|
}
|
|
|
|
else { self.name() };
|
|
|
|
|
|
|
|
cx.item_fn_poly(name,
|
|
|
|
args_ast,
|
|
|
|
if try {
|
|
|
|
cx.ty_option(cx.ty_nil_ast_builder())
|
|
|
|
} else {
|
|
|
|
cx.ty_nil_ast_builder()
|
|
|
|
},
|
|
|
|
self.get_params(),
|
|
|
|
cx.expr_block(body))
|
2012-07-16 14:44:27 -07:00
|
|
|
}
|
|
|
|
}
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
2012-07-11 15:00:40 -07:00
|
|
|
|
|
|
|
fn to_ty(cx: ext_ctxt) -> @ast::ty {
|
2012-07-24 16:58:48 -07:00
|
|
|
cx.ty_path_ast_builder(path(self.name(), self.span())
|
2012-07-17 16:49:54 -07:00
|
|
|
.add_tys(cx.ty_vars(self.get_params())))
|
2012-07-11 15:00:40 -07:00
|
|
|
}
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl state: to_type_decls {
|
2012-07-11 16:49:02 -07:00
|
|
|
fn to_type_decls(cx: ext_ctxt) -> ~[@ast::item] {
|
2012-07-30 16:01:07 -07:00
|
|
|
debug!{"pipec: to_type_decls"};
|
2012-07-05 16:07:53 -07:00
|
|
|
// This compiles into two different type declarations. Say the
|
|
|
|
// state is called ping. This will generate both `ping` and
|
|
|
|
// `ping_message`. The first contains data that the user cares
|
|
|
|
// about. The second is the same thing, but extended with a
|
|
|
|
// next packet pointer, which is used under the covers.
|
|
|
|
|
|
|
|
let name = self.data_name();
|
|
|
|
|
2012-07-11 16:49:02 -07:00
|
|
|
let mut items_msg = ~[];
|
2012-07-05 16:07:53 -07:00
|
|
|
|
|
|
|
for self.messages.each |m| {
|
2012-08-17 11:26:35 -07:00
|
|
|
let message(name, span, tys, this, next) = m;
|
2012-07-16 14:44:27 -07:00
|
|
|
|
2012-08-06 12:34:08 -07:00
|
|
|
let tys = match next {
|
2012-08-03 19:59:04 -07:00
|
|
|
some({state: next, tys: next_tys}) => {
|
2012-07-16 14:44:27 -07:00
|
|
|
let next = this.proto.get_state(next);
|
|
|
|
let next_name = next.data_name();
|
|
|
|
|
2012-08-06 12:34:08 -07:00
|
|
|
let dir = match this.dir {
|
2012-08-03 19:59:04 -07:00
|
|
|
send => @~"server",
|
|
|
|
recv => @~"client"
|
2012-07-16 14:44:27 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
vec::append_one(tys,
|
2012-07-17 16:49:54 -07:00
|
|
|
cx.ty_path_ast_builder((dir + next_name)
|
2012-07-16 14:44:27 -07:00
|
|
|
.add_tys(next_tys)))
|
|
|
|
}
|
2012-08-03 19:59:04 -07:00
|
|
|
none => tys
|
2012-07-05 16:07:53 -07:00
|
|
|
};
|
|
|
|
|
2012-08-17 11:26:35 -07:00
|
|
|
let v = cx.variant(name, span, tys);
|
2012-07-05 16:07:53 -07:00
|
|
|
|
|
|
|
vec::push(items_msg, v);
|
|
|
|
}
|
|
|
|
|
2012-08-08 19:51:19 -07:00
|
|
|
~[cx.item_enum_poly(name,
|
2012-08-17 11:26:35 -07:00
|
|
|
self.span,
|
2012-08-08 19:51:19 -07:00
|
|
|
ast::enum_def({ variants: items_msg,
|
|
|
|
common: none }),
|
2012-08-08 17:14:25 -07:00
|
|
|
self.ty_params)]
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
|
2012-07-11 16:49:02 -07:00
|
|
|
fn to_endpoint_decls(cx: ext_ctxt, dir: direction) -> ~[@ast::item] {
|
2012-07-30 16:01:07 -07:00
|
|
|
debug!{"pipec: to_endpoint_decls"};
|
2012-08-06 12:34:08 -07:00
|
|
|
let dir = match dir {
|
2012-08-03 19:59:04 -07:00
|
|
|
send => (*self).dir,
|
|
|
|
recv => (*self).dir.reverse()
|
2012-07-05 16:07:53 -07:00
|
|
|
};
|
|
|
|
let mut items = ~[];
|
|
|
|
for self.messages.each |m| {
|
|
|
|
if dir == send {
|
2012-08-07 11:46:52 -07:00
|
|
|
vec::push(items, m.gen_send(cx, true));
|
|
|
|
vec::push(items, m.gen_send(cx, false));
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-23 18:50:53 -07:00
|
|
|
if !self.proto.is_bounded() {
|
|
|
|
vec::push(items,
|
|
|
|
cx.item_ty_poly(
|
|
|
|
self.data_name(),
|
2012-08-17 11:26:35 -07:00
|
|
|
self.span,
|
2012-07-23 18:50:53 -07:00
|
|
|
cx.ty_path_ast_builder(
|
|
|
|
(@~"pipes" + @(dir.to_str() + ~"_packet"))
|
|
|
|
.add_ty(cx.ty_path_ast_builder(
|
|
|
|
(self.proto.name + self.data_name())
|
|
|
|
.add_tys(cx.ty_vars(self.ty_params))))),
|
|
|
|
self.ty_params));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
vec::push(items,
|
|
|
|
cx.item_ty_poly(
|
|
|
|
self.data_name(),
|
2012-08-17 11:26:35 -07:00
|
|
|
self.span,
|
2012-07-23 18:50:53 -07:00
|
|
|
cx.ty_path_ast_builder(
|
|
|
|
(@~"pipes" + @(dir.to_str()
|
|
|
|
+ ~"_packet_buffered"))
|
|
|
|
.add_tys(~[cx.ty_path_ast_builder(
|
|
|
|
(self.proto.name + self.data_name())
|
|
|
|
.add_tys(cx.ty_vars(self.ty_params))),
|
2012-07-24 18:00:08 -07:00
|
|
|
self.proto.buffer_ty_path(cx)])),
|
2012-07-23 18:50:53 -07:00
|
|
|
self.ty_params));
|
|
|
|
};
|
2012-07-05 16:07:53 -07:00
|
|
|
items
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl protocol: gen_init {
|
2012-07-05 16:07:53 -07:00
|
|
|
fn gen_init(cx: ext_ctxt) -> @ast::item {
|
2012-07-23 18:50:53 -07:00
|
|
|
let ext_cx = cx;
|
|
|
|
|
2012-07-30 16:01:07 -07:00
|
|
|
debug!{"gen_init"};
|
2012-07-05 16:07:53 -07:00
|
|
|
let start_state = self.states[0];
|
|
|
|
|
2012-07-23 18:50:53 -07:00
|
|
|
let body = if !self.is_bounded() {
|
2012-08-06 12:34:08 -07:00
|
|
|
match start_state.dir {
|
2012-08-03 19:59:04 -07:00
|
|
|
send => #ast { pipes::entangle() },
|
|
|
|
recv => {
|
2012-07-23 18:50:53 -07:00
|
|
|
#ast {{
|
|
|
|
let (s, c) = pipes::entangle();
|
|
|
|
(c, s)
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let body = self.gen_init_bounded(ext_cx);
|
2012-08-06 12:34:08 -07:00
|
|
|
match start_state.dir {
|
2012-08-03 19:59:04 -07:00
|
|
|
send => body,
|
|
|
|
recv => {
|
2012-07-23 18:50:53 -07:00
|
|
|
#ast {{
|
|
|
|
let (s, c) = $(body);
|
|
|
|
(c, s)
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
}
|
2012-07-05 16:07:53 -07:00
|
|
|
};
|
|
|
|
|
2012-07-30 16:01:07 -07:00
|
|
|
cx.parse_item(fmt!{"fn init%s() -> (client::%s, server::%s)\
|
2012-07-23 18:50:53 -07:00
|
|
|
{ import pipes::has_buffer; %s }",
|
2012-07-16 17:27:04 -07:00
|
|
|
start_state.ty_params.to_source(),
|
|
|
|
start_state.to_ty(cx).to_source(),
|
|
|
|
start_state.to_ty(cx).to_source(),
|
2012-07-30 16:01:07 -07:00
|
|
|
body.to_source()})
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
|
2012-07-23 18:50:53 -07:00
|
|
|
fn gen_buffer_init(ext_cx: ext_ctxt) -> @ast::expr {
|
|
|
|
ext_cx.rec(self.states.map_to_vec(|s| {
|
2012-07-24 18:00:08 -07:00
|
|
|
let fty = s.to_ty(ext_cx);
|
2012-07-23 18:50:53 -07:00
|
|
|
ext_cx.field_imm(s.name, #ast { pipes::mk_packet::<$(fty)>() })
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gen_init_bounded(ext_cx: ext_ctxt) -> @ast::expr {
|
2012-07-30 16:01:07 -07:00
|
|
|
debug!{"gen_init_bounded"};
|
2012-07-23 18:50:53 -07:00
|
|
|
let buffer_fields = self.gen_buffer_init(ext_cx);
|
|
|
|
|
|
|
|
let buffer = #ast {
|
|
|
|
~{header: pipes::buffer_header(),
|
|
|
|
data: $(buffer_fields)}
|
|
|
|
};
|
|
|
|
|
|
|
|
let entangle_body = ext_cx.block_expr(
|
|
|
|
ext_cx.block(
|
|
|
|
self.states.map_to_vec(
|
|
|
|
|s| ext_cx.parse_stmt(
|
2012-07-30 16:01:07 -07:00
|
|
|
fmt!{"data.%s.set_buffer(buffer)", *s.name})),
|
2012-07-23 18:50:53 -07:00
|
|
|
ext_cx.parse_expr(
|
2012-07-30 16:01:07 -07:00
|
|
|
fmt!{"ptr::addr_of(data.%s)", *self.states[0].name})));
|
2012-07-23 18:50:53 -07:00
|
|
|
|
|
|
|
#ast {{
|
|
|
|
let buffer = $(buffer);
|
|
|
|
do pipes::entangle_buffer(buffer) |buffer, data| {
|
|
|
|
$(entangle_body)
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
2012-07-24 18:00:08 -07:00
|
|
|
fn buffer_ty_path(cx: ext_ctxt) -> @ast::ty {
|
2012-07-25 10:13:37 -07:00
|
|
|
let mut params: ~[ast::ty_param] = ~[];
|
2012-07-24 18:00:08 -07:00
|
|
|
for (copy self.states).each |s| {
|
|
|
|
for s.ty_params.each |tp| {
|
2012-08-06 12:34:08 -07:00
|
|
|
match params.find(|tpp| *tp.ident == *tpp.ident) {
|
2012-08-03 19:59:04 -07:00
|
|
|
none => vec::push(params, tp),
|
|
|
|
_ => ()
|
2012-07-24 18:00:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-15 15:08:59 -07:00
|
|
|
cx.ty_path_ast_builder(path(@~"__Buffer", self.span)
|
2012-07-24 18:00:08 -07:00
|
|
|
.add_tys(cx.ty_vars(params)))
|
|
|
|
}
|
|
|
|
|
2012-07-23 18:50:53 -07:00
|
|
|
fn gen_buffer_type(cx: ext_ctxt) -> @ast::item {
|
|
|
|
let ext_cx = cx;
|
2012-07-25 10:13:37 -07:00
|
|
|
let mut params: ~[ast::ty_param] = ~[];
|
2012-07-24 18:00:08 -07:00
|
|
|
let fields = do (copy self.states).map_to_vec |s| {
|
|
|
|
for s.ty_params.each |tp| {
|
2012-08-06 12:34:08 -07:00
|
|
|
match params.find(|tpp| *tp.ident == *tpp.ident) {
|
2012-08-03 19:59:04 -07:00
|
|
|
none => vec::push(params, tp),
|
|
|
|
_ => ()
|
2012-07-24 18:00:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
let ty = s.to_ty(cx);
|
|
|
|
let fty = #ast[ty] {
|
|
|
|
pipes::packet<$(ty)>
|
|
|
|
};
|
|
|
|
cx.ty_field_imm(s.name, fty)
|
|
|
|
};
|
|
|
|
|
|
|
|
cx.item_ty_poly(
|
2012-08-15 15:08:59 -07:00
|
|
|
@~"__Buffer",
|
2012-08-17 11:26:35 -07:00
|
|
|
cx.empty_span(),
|
2012-07-24 18:00:08 -07:00
|
|
|
cx.ty_rec(fields),
|
|
|
|
params)
|
2012-07-23 18:50:53 -07:00
|
|
|
}
|
|
|
|
|
2012-07-05 16:07:53 -07:00
|
|
|
fn compile(cx: ext_ctxt) -> @ast::item {
|
|
|
|
let mut items = ~[self.gen_init(cx)];
|
|
|
|
let mut client_states = ~[];
|
|
|
|
let mut server_states = ~[];
|
|
|
|
|
2012-07-05 18:01:11 -07:00
|
|
|
// :(
|
|
|
|
for (copy self.states).each |s| {
|
2012-07-05 16:07:53 -07:00
|
|
|
items += s.to_type_decls(cx);
|
|
|
|
|
|
|
|
client_states += s.to_endpoint_decls(cx, send);
|
|
|
|
server_states += s.to_endpoint_decls(cx, recv);
|
|
|
|
}
|
|
|
|
|
2012-07-23 14:46:39 -07:00
|
|
|
if self.is_bounded() {
|
2012-07-23 18:50:53 -07:00
|
|
|
vec::push(items, self.gen_buffer_type(cx))
|
2012-07-23 14:46:39 -07:00
|
|
|
}
|
|
|
|
|
2012-07-05 16:07:53 -07:00
|
|
|
vec::push(items,
|
2012-07-13 22:57:48 -07:00
|
|
|
cx.item_mod(@~"client",
|
2012-08-17 11:26:35 -07:00
|
|
|
self.span,
|
2012-07-05 16:07:53 -07:00
|
|
|
client_states));
|
|
|
|
vec::push(items,
|
2012-07-13 22:57:48 -07:00
|
|
|
cx.item_mod(@~"server",
|
2012-08-17 11:26:35 -07:00
|
|
|
self.span,
|
2012-07-05 16:07:53 -07:00
|
|
|
server_states));
|
|
|
|
|
2012-08-17 11:26:35 -07:00
|
|
|
cx.item_mod(self.name, self.span, items)
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-31 10:27:51 -07:00
|
|
|
trait to_source {
|
2012-07-05 16:07:53 -07:00
|
|
|
// Takes a thing and generates a string containing rust code for it.
|
2012-07-13 22:57:48 -07:00
|
|
|
fn to_source() -> ~str;
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl @ast::item: to_source {
|
2012-07-13 22:57:48 -07:00
|
|
|
fn to_source() -> ~str {
|
2012-07-05 16:07:53 -07:00
|
|
|
item_to_str(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl ~[@ast::item]: to_source {
|
2012-07-13 22:57:48 -07:00
|
|
|
fn to_source() -> ~str {
|
|
|
|
str::connect(self.map(|i| i.to_source()), ~"\n\n")
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl @ast::ty: to_source {
|
2012-07-13 22:57:48 -07:00
|
|
|
fn to_source() -> ~str {
|
2012-07-05 16:07:53 -07:00
|
|
|
ty_to_str(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl ~[@ast::ty]: to_source {
|
2012-07-13 22:57:48 -07:00
|
|
|
fn to_source() -> ~str {
|
|
|
|
str::connect(self.map(|i| i.to_source()), ~", ")
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl ~[ast::ty_param]: to_source {
|
2012-07-13 22:57:48 -07:00
|
|
|
fn to_source() -> ~str {
|
2012-07-05 16:07:53 -07:00
|
|
|
pprust::typarams_to_str(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl @ast::expr: to_source {
|
2012-07-13 22:57:48 -07:00
|
|
|
fn to_source() -> ~str {
|
2012-07-05 16:07:53 -07:00
|
|
|
pprust::expr_to_str(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-11 15:00:40 -07:00
|
|
|
trait ext_ctxt_parse_utils {
|
|
|
|
fn parse_item(s: ~str) -> @ast::item;
|
|
|
|
fn parse_expr(s: ~str) -> @ast::expr;
|
2012-07-23 18:50:53 -07:00
|
|
|
fn parse_stmt(s: ~str) -> @ast::stmt;
|
2012-07-11 15:00:40 -07:00
|
|
|
}
|
|
|
|
|
2012-08-07 18:10:06 -07:00
|
|
|
impl ext_ctxt: ext_ctxt_parse_utils {
|
2012-07-13 22:57:48 -07:00
|
|
|
fn parse_item(s: ~str) -> @ast::item {
|
2012-07-05 16:07:53 -07:00
|
|
|
let res = parse::parse_item_from_source_str(
|
2012-07-13 22:57:48 -07:00
|
|
|
~"***protocol expansion***",
|
2012-07-05 16:07:53 -07:00
|
|
|
@(copy s),
|
|
|
|
self.cfg(),
|
2012-07-11 16:49:02 -07:00
|
|
|
~[],
|
2012-07-05 16:07:53 -07:00
|
|
|
self.parse_sess());
|
2012-08-06 12:34:08 -07:00
|
|
|
match res {
|
2012-08-03 19:59:04 -07:00
|
|
|
some(ast) => ast,
|
|
|
|
none => {
|
2012-07-30 16:01:07 -07:00
|
|
|
error!{"Parse error with ```\n%s\n```", s};
|
2012-07-05 16:07:53 -07:00
|
|
|
fail
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-23 18:50:53 -07:00
|
|
|
fn parse_stmt(s: ~str) -> @ast::stmt {
|
|
|
|
parse::parse_stmt_from_source_str(
|
|
|
|
~"***protocol expansion***",
|
|
|
|
@(copy s),
|
|
|
|
self.cfg(),
|
|
|
|
~[],
|
|
|
|
self.parse_sess())
|
|
|
|
}
|
|
|
|
|
2012-07-13 22:57:48 -07:00
|
|
|
fn parse_expr(s: ~str) -> @ast::expr {
|
2012-07-05 16:07:53 -07:00
|
|
|
parse::parse_expr_from_source_str(
|
2012-07-13 22:57:48 -07:00
|
|
|
~"***protocol expansion***",
|
2012-07-05 16:07:53 -07:00
|
|
|
@(copy s),
|
|
|
|
self.cfg(),
|
|
|
|
self.parse_sess())
|
|
|
|
}
|
|
|
|
}
|