2012-12-03 16:48:01 -08:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-07-05 16:07:53 -07:00
|
|
|
// A protocol compiler for Rust.
|
|
|
|
|
2012-09-04 11:37:29 -07:00
|
|
|
use ast::ident;
|
2013-01-30 09:56:33 -08:00
|
|
|
use codemap::dummy_sp;
|
2012-12-06 16:19:50 -08:00
|
|
|
use ext::base::ext_ctxt;
|
2013-01-25 16:57:39 -08:00
|
|
|
use ext::pipes::ast_builder::{append_types, ext_ctxt_ast_builder, path};
|
|
|
|
use ext::pipes::ast_builder::{path_global};
|
2012-12-13 13:05:22 -08:00
|
|
|
use ext::pipes::proto::*;
|
|
|
|
use ext::quote::rt::*;
|
2012-12-23 17:41:37 -05:00
|
|
|
use parse::*;
|
|
|
|
use util::interner;
|
|
|
|
|
|
|
|
use core::dvec::DVec;
|
2013-01-08 19:37:25 -08:00
|
|
|
use core::prelude::*;
|
2012-12-23 17:41:37 -05:00
|
|
|
use core::str;
|
|
|
|
use core::to_str::ToStr;
|
|
|
|
use core::vec;
|
2012-07-23 18:50:53 -07:00
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub trait gen_send {
|
2012-08-07 11:46:52 -07:00
|
|
|
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item;
|
2012-11-29 18:37:33 -08:00
|
|
|
fn to_ty(cx: ext_ctxt) -> @ast::Ty;
|
2012-07-17 16:49:54 -07:00
|
|
|
}
|
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub trait to_type_decls {
|
2012-07-17 16:49:54 -07:00
|
|
|
fn to_type_decls(cx: ext_ctxt) -> ~[@ast::item];
|
|
|
|
fn to_endpoint_decls(cx: ext_ctxt, dir: direction) -> ~[@ast::item];
|
|
|
|
}
|
|
|
|
|
2013-01-25 16:57:39 -08:00
|
|
|
pub trait gen_init {
|
2012-07-17 16:49:54 -07:00
|
|
|
fn gen_init(cx: ext_ctxt) -> @ast::item;
|
|
|
|
fn compile(cx: ext_ctxt) -> @ast::item;
|
2012-11-29 18:37:33 -08:00
|
|
|
fn buffer_ty_path(cx: ext_ctxt) -> @ast::Ty;
|
|
|
|
fn gen_buffer_type(cx: ext_ctxt) -> @ast::item;
|
|
|
|
fn gen_buffer_init(ext_cx: ext_ctxt) -> @ast::expr;
|
|
|
|
fn gen_init_bounded(ext_cx: ext_ctxt) -> @ast::expr;
|
2012-07-17 16:49:54 -07:00
|
|
|
}
|
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub impl message: gen_send {
|
2012-08-07 11:46:52 -07:00
|
|
|
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item {
|
2012-08-22 17:24:52 -07:00
|
|
|
debug!("pipec: gen_send");
|
2012-08-06 12:34:08 -07:00
|
|
|
match self {
|
2012-12-04 10:50:00 -08:00
|
|
|
message(ref _id, span, tys, this,
|
2013-01-17 08:55:28 -08:00
|
|
|
Some(next_state {state: ref next, tys: next_tys})) => {
|
2012-08-07 11:46:52 -07:00
|
|
|
debug!("pipec: next state exists");
|
2012-12-04 10:50:00 -08:00
|
|
|
let next = this.proto.get_state((*next));
|
2012-07-05 18:01:11 -07:00
|
|
|
assert next_tys.len() == next.ty_params.len();
|
2012-07-18 16:18:02 -07:00
|
|
|
let arg_names = tys.mapi(|i, _ty| cx.ident_of(~"x_"+i.to_str()));
|
2012-07-05 16:07:53 -07:00
|
|
|
|
|
|
|
let args_ast = (arg_names, tys).map(
|
2012-10-04 19:58:31 -07:00
|
|
|
|n, t| cx.arg(*n, *t)
|
2012-07-05 16:07:53 -07:00
|
|
|
);
|
|
|
|
|
2012-07-20 19:06:32 -07:00
|
|
|
let pipe_ty = cx.ty_path_ast_builder(
|
2012-07-18 16:18:02 -07:00
|
|
|
path(~[this.data_name()], span)
|
2012-12-23 17:41:37 -05:00
|
|
|
.add_tys(cx.ty_vars_global(this.ty_params)));
|
2012-07-05 16:07:53 -07:00
|
|
|
let args_ast = vec::append(
|
2012-10-04 19:58:31 -07:00
|
|
|
~[cx.arg(cx.ident_of(~"pipe"),
|
|
|
|
pipe_ty)],
|
2012-07-05 16:07:53 -07:00
|
|
|
args_ast);
|
|
|
|
|
2012-07-23 18:50:53 -07:00
|
|
|
let mut body = ~"{\n";
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("use super::%s;\n", self.name());
|
2012-07-23 18:50:53 -07:00
|
|
|
|
|
|
|
if this.proto.is_bounded() {
|
2012-08-06 12:34:08 -07:00
|
|
|
let (sp, rp) = match (this.dir, next.dir) {
|
2012-09-10 14:57:23 -07:00
|
|
|
(send, send) => (~"move c", ~"move s"),
|
2012-08-03 19:59:04 -07:00
|
|
|
(send, recv) => (~"s", ~"c"),
|
|
|
|
(recv, send) => (~"s", ~"c"),
|
2012-09-10 14:57:23 -07:00
|
|
|
(recv, recv) => (~"move c", ~"move 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-12-23 17:41:37 -05:00
|
|
|
body += fmt!("let %s = ::pipes::SendPacketBuffered(\
|
|
|
|
::ptr::addr_of(&(b.buffer.data.%s)));\n",
|
2012-07-18 16:18:02 -07:00
|
|
|
sp, next.name);
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("let %s = ::pipes::RecvPacketBuffered(\
|
|
|
|
::ptr::addr_of(&(b.buffer.data.%s)));\n",
|
2012-08-22 17:24: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-09-10 14:57:23 -07:00
|
|
|
(send, send) => "(move c, move s)",
|
2012-08-07 11:46:52 -07:00
|
|
|
(send, recv) => "(s, c)",
|
|
|
|
(recv, send) => "(s, c)",
|
2012-09-10 14:57:23 -07:00
|
|
|
(recv, recv) => "(move c, move s)"
|
2012-07-23 18:50:53 -07:00
|
|
|
};
|
|
|
|
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("let %s = ::pipes::entangle();\n", pat);
|
2012-07-23 18:50:53 -07:00
|
|
|
}
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("let message = %s(%s);\n",
|
2012-07-18 16:18:02 -07:00
|
|
|
self.name(),
|
|
|
|
str::connect(vec::append_one(
|
2012-09-21 18:43:30 -07:00
|
|
|
arg_names.map(|x| ~"move " + cx.str_of(*x)),
|
2012-09-10 14:57:23 -07:00
|
|
|
~"move s"), ~", "));
|
2012-08-07 11:46:52 -07:00
|
|
|
|
|
|
|
if !try {
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("::pipes::send(move pipe, move message);\n");
|
2012-08-07 11:46:52 -07:00
|
|
|
// return the new channel
|
2012-09-10 14:57:23 -07:00
|
|
|
body += ~"move c }";
|
2012-08-07 11:46:52 -07:00
|
|
|
}
|
|
|
|
else {
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("if ::pipes::send(move pipe, move message) {\n \
|
|
|
|
::pipes::rt::make_some(move 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-07-18 16:18:02 -07:00
|
|
|
let mut rty = cx.ty_path_ast_builder(path(~[next.data_name()],
|
2012-08-07 11:46:52 -07:00
|
|
|
span)
|
|
|
|
.add_tys(next_tys));
|
|
|
|
if try {
|
|
|
|
rty = cx.ty_option(rty);
|
|
|
|
}
|
|
|
|
|
2012-07-18 16:18:02 -07:00
|
|
|
let name = cx.ident_of(if try { ~"try_" + self.name()
|
|
|
|
} else { self.name() } );
|
2012-08-07 11:46:52 -07:00
|
|
|
|
|
|
|
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-12-04 10:50:00 -08:00
|
|
|
message(ref _id, span, tys, this, None) => {
|
2012-08-22 17:24:52 -07:00
|
|
|
debug!("pipec: no next state");
|
2012-07-18 16:18:02 -07:00
|
|
|
let arg_names = tys.mapi(|i, _ty| (~"x_" + i.to_str()));
|
2012-08-07 11:46:52 -07:00
|
|
|
|
|
|
|
let args_ast = (arg_names, tys).map(
|
2012-10-04 19:58:31 -07:00
|
|
|
|n, t| cx.arg(cx.ident_of(*n), *t)
|
2012-08-07 11:46:52 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
let args_ast = vec::append(
|
2012-10-04 19:58:31 -07:00
|
|
|
~[cx.arg(cx.ident_of(~"pipe"),
|
2012-08-07 11:46:52 -07:00
|
|
|
cx.ty_path_ast_builder(
|
2012-07-18 16:18:02 -07:00
|
|
|
path(~[this.data_name()], span)
|
2012-12-23 17:41:37 -05:00
|
|
|
.add_tys(cx.ty_vars_global(
|
|
|
|
this.ty_params))))],
|
2012-08-07 11:46:52 -07:00
|
|
|
args_ast);
|
|
|
|
|
|
|
|
let message_args = if arg_names.len() == 0 {
|
|
|
|
~""
|
|
|
|
}
|
|
|
|
else {
|
2012-09-21 18:43:30 -07:00
|
|
|
~"(" + str::connect(arg_names.map(|x| ~"move " + *x),
|
2012-09-10 14:57:23 -07:00
|
|
|
~", ") + ~")"
|
2012-08-07 11:46:52 -07:00
|
|
|
};
|
2012-07-16 14:44:27 -07:00
|
|
|
|
2012-08-07 11:46:52 -07:00
|
|
|
let mut body = ~"{ ";
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("use super::%s;\n", self.name());
|
|
|
|
body += fmt!("let message = %s%s;\n",
|
2012-07-18 16:18:02 -07:00
|
|
|
self.name(),
|
2012-08-22 17:24:52 -07:00
|
|
|
message_args);
|
2012-08-07 11:46:52 -07:00
|
|
|
|
|
|
|
if !try {
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("::pipes::send(move pipe, move message);\n");
|
2012-08-07 11:46:52 -07:00
|
|
|
body += ~" }";
|
|
|
|
} else {
|
2012-12-23 17:41:37 -05:00
|
|
|
body += fmt!("if ::pipes::send(move pipe, move message) \
|
|
|
|
{ \
|
|
|
|
::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 {
|
2012-07-18 16:18:02 -07:00
|
|
|
~"try_" + self.name()
|
2012-08-07 11:46:52 -07:00
|
|
|
}
|
|
|
|
else { self.name() };
|
|
|
|
|
2012-07-18 16:18:02 -07:00
|
|
|
cx.item_fn_poly(cx.ident_of(name),
|
2012-08-07 11:46:52 -07:00
|
|
|
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
|
|
|
|
2012-10-15 14:56:42 -07:00
|
|
|
fn to_ty(cx: ext_ctxt) -> @ast::Ty {
|
2012-07-18 16:18:02 -07:00
|
|
|
cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span())
|
2012-12-23 17:41:37 -05:00
|
|
|
.add_tys(cx.ty_vars_global(self.get_params())))
|
2012-07-11 15:00:40 -07:00
|
|
|
}
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub impl state: to_type_decls {
|
2012-07-11 16:49:02 -07:00
|
|
|
fn to_type_decls(cx: ext_ctxt) -> ~[@ast::item] {
|
2012-08-22 17:24:52 -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-09-19 16:55:01 -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 {
|
2013-01-17 08:55:28 -08:00
|
|
|
Some(next_state { state: ref next, tys: next_tys }) => {
|
2012-12-04 10:50:00 -08:00
|
|
|
let next = this.proto.get_state((*next));
|
2012-07-18 16:18:02 -07:00
|
|
|
let next_name = cx.str_of(next.data_name());
|
2012-07-16 14:44:27 -07:00
|
|
|
|
2012-08-06 12:34:08 -07:00
|
|
|
let dir = match this.dir {
|
2012-07-18 16:18:02 -07:00
|
|
|
send => ~"server",
|
|
|
|
recv => ~"client"
|
2012-07-16 14:44:27 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
vec::append_one(tys,
|
2012-07-18 16:18:02 -07:00
|
|
|
cx.ty_path_ast_builder(
|
|
|
|
path(~[cx.ident_of(dir),
|
|
|
|
cx.ident_of(next_name)], span)
|
|
|
|
.add_tys(next_tys)))
|
2012-07-16 14:44:27 -07:00
|
|
|
}
|
2012-08-20 12:23:37 -07:00
|
|
|
None => tys
|
2012-07-05 16:07:53 -07:00
|
|
|
};
|
|
|
|
|
2012-07-18 16:18:02 -07:00
|
|
|
let v = cx.variant(cx.ident_of(name), span, tys);
|
2012-07-05 16:07:53 -07:00
|
|
|
|
2012-09-26 17:33:34 -07:00
|
|
|
items_msg.push(v);
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
|
|
|
|
2013-01-15 16:05:20 -08:00
|
|
|
~[
|
|
|
|
cx.item_enum_poly(
|
|
|
|
name,
|
|
|
|
self.span,
|
|
|
|
ast::enum_def(enum_def_ {
|
|
|
|
variants: items_msg,
|
|
|
|
common: None }),
|
2013-01-28 10:46:43 -08:00
|
|
|
cx.strip_bounds(self.ty_params)
|
2013-01-15 16:05:20 -08:00
|
|
|
)
|
|
|
|
]
|
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-08-22 17:24:52 -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-09-26 17:33:34 -07:00
|
|
|
items.push(m.gen_send(cx, true));
|
|
|
|
items.push(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() {
|
2012-09-26 17:33:34 -07:00
|
|
|
items.push(
|
|
|
|
cx.item_ty_poly(
|
|
|
|
self.data_name(),
|
|
|
|
self.span,
|
|
|
|
cx.ty_path_ast_builder(
|
2012-12-23 17:41:37 -05:00
|
|
|
path_global(~[cx.ident_of(~"pipes"),
|
|
|
|
cx.ident_of(dir.to_str() + ~"Packet")],
|
2012-11-12 19:32:48 -08:00
|
|
|
dummy_sp())
|
2012-09-26 17:33:34 -07:00
|
|
|
.add_ty(cx.ty_path_ast_builder(
|
2012-12-23 17:41:37 -05:00
|
|
|
path(~[cx.ident_of(~"super"),
|
2012-09-26 17:33:34 -07:00
|
|
|
self.data_name()],
|
2012-11-12 19:32:48 -08:00
|
|
|
dummy_sp())
|
2012-12-23 17:41:37 -05:00
|
|
|
.add_tys(cx.ty_vars_global(self.ty_params))))),
|
2013-01-28 10:46:43 -08:00
|
|
|
cx.strip_bounds(self.ty_params)));
|
2012-07-23 18:50:53 -07:00
|
|
|
}
|
|
|
|
else {
|
2012-09-26 17:33:34 -07:00
|
|
|
items.push(
|
|
|
|
cx.item_ty_poly(
|
|
|
|
self.data_name(),
|
|
|
|
self.span,
|
|
|
|
cx.ty_path_ast_builder(
|
2012-12-23 17:41:37 -05:00
|
|
|
path_global(~[cx.ident_of(~"pipes"),
|
|
|
|
cx.ident_of(dir.to_str()
|
|
|
|
+ ~"PacketBuffered")],
|
2012-11-12 19:32:48 -08:00
|
|
|
dummy_sp())
|
2012-09-26 17:33:34 -07:00
|
|
|
.add_tys(~[cx.ty_path_ast_builder(
|
2012-12-23 17:41:37 -05:00
|
|
|
path(~[cx.ident_of(~"super"),
|
2012-09-26 17:33:34 -07:00
|
|
|
self.data_name()],
|
2012-12-23 17:41:37 -05:00
|
|
|
dummy_sp())
|
|
|
|
.add_tys(cx.ty_vars_global(self.ty_params))),
|
2012-09-26 17:33:34 -07:00
|
|
|
self.proto.buffer_ty_path(cx)])),
|
2013-01-28 10:46:43 -08:00
|
|
|
cx.strip_bounds(self.ty_params)));
|
2012-07-23 18:50:53 -07:00
|
|
|
};
|
2012-07-05 16:07:53 -07:00
|
|
|
items
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub impl protocol: gen_init {
|
2012-12-06 16:19:50 -08:00
|
|
|
|
|
|
|
fn gen_init(cx: ext_ctxt) -> @ast::item {
|
|
|
|
let ext_cx = cx;
|
|
|
|
|
|
|
|
debug!("gen_init");
|
|
|
|
let start_state = self.states[0];
|
|
|
|
|
|
|
|
let body = if !self.is_bounded() {
|
|
|
|
match start_state.dir {
|
2012-12-23 17:41:37 -05:00
|
|
|
send => quote_expr!( ::pipes::entangle() ),
|
2012-12-06 16:19:50 -08:00
|
|
|
recv => {
|
|
|
|
quote_expr!({
|
2012-12-23 17:41:37 -05:00
|
|
|
let (s, c) = ::pipes::entangle();
|
2012-12-06 16:19:50 -08:00
|
|
|
(move c, move s)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let body = self.gen_init_bounded(ext_cx);
|
|
|
|
match start_state.dir {
|
|
|
|
send => body,
|
|
|
|
recv => {
|
|
|
|
quote_expr!({
|
|
|
|
let (s, c) = $body;
|
|
|
|
(move c, move s)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
cx.parse_item(fmt!("pub fn init%s() -> (client::%s, server::%s)\
|
|
|
|
{ use pipes::HasBuffer; %s }",
|
|
|
|
start_state.ty_params.to_source(cx),
|
|
|
|
start_state.to_ty(cx).to_source(cx),
|
|
|
|
start_state.to_ty(cx).to_source(cx),
|
|
|
|
body.to_source(cx)))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gen_buffer_init(ext_cx: ext_ctxt) -> @ast::expr {
|
|
|
|
ext_cx.rec(self.states.map_to_vec(|s| {
|
|
|
|
let fty = s.to_ty(ext_cx);
|
|
|
|
ext_cx.field_imm(ext_cx.ident_of(s.name),
|
|
|
|
quote_expr!(
|
2012-12-23 17:41:37 -05:00
|
|
|
::pipes::mk_packet::<$fty>()
|
2012-12-06 16:19:50 -08:00
|
|
|
))
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2013-01-29 15:06:05 -08:00
|
|
|
#[cfg(stage0)]
|
|
|
|
fn gen_init_bounded(ext_cx: ext_ctxt) -> @ast::expr {
|
|
|
|
debug!("gen_init_bounded");
|
|
|
|
let buffer_fields = self.gen_buffer_init(ext_cx);
|
|
|
|
let buffer = quote_expr!(~{
|
|
|
|
header: ::pipes::BufferHeader(),
|
|
|
|
data: $buffer_fields,
|
|
|
|
});
|
|
|
|
|
|
|
|
let entangle_body = ext_cx.block_expr(
|
|
|
|
ext_cx.block(
|
|
|
|
self.states.map_to_vec(
|
|
|
|
|s| ext_cx.parse_stmt(
|
|
|
|
fmt!("data.%s.set_buffer_(buffer)",
|
|
|
|
s.name))),
|
|
|
|
ext_cx.parse_expr(
|
|
|
|
fmt!("::ptr::addr_of(&(data.%s))",
|
|
|
|
self.states[0].name))));
|
|
|
|
|
|
|
|
quote_expr!({
|
|
|
|
let buffer = $buffer;
|
|
|
|
do ::pipes::entangle_buffer(move buffer) |buffer, data| {
|
|
|
|
$entangle_body
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
#[cfg(stage1)]
|
|
|
|
#[cfg(stage2)]
|
2012-12-06 16:19:50 -08:00
|
|
|
fn gen_init_bounded(ext_cx: ext_ctxt) -> @ast::expr {
|
|
|
|
debug!("gen_init_bounded");
|
|
|
|
let buffer_fields = self.gen_buffer_init(ext_cx);
|
2013-01-24 11:37:36 -08:00
|
|
|
let buffer = quote_expr!(~::pipes::Buffer {
|
|
|
|
header: ::pipes::BufferHeader(),
|
|
|
|
data: $buffer_fields,
|
|
|
|
});
|
2012-12-06 16:19:50 -08:00
|
|
|
|
|
|
|
let entangle_body = ext_cx.block_expr(
|
|
|
|
ext_cx.block(
|
|
|
|
self.states.map_to_vec(
|
|
|
|
|s| ext_cx.parse_stmt(
|
|
|
|
fmt!("data.%s.set_buffer_(buffer)",
|
|
|
|
s.name))),
|
|
|
|
ext_cx.parse_expr(
|
2012-12-23 17:41:37 -05:00
|
|
|
fmt!("::ptr::addr_of(&(data.%s))",
|
2012-12-06 16:19:50 -08:00
|
|
|
self.states[0].name))));
|
|
|
|
|
|
|
|
quote_expr!({
|
|
|
|
let buffer = $buffer;
|
2012-12-23 17:41:37 -05:00
|
|
|
do ::pipes::entangle_buffer(move buffer) |buffer, data| {
|
2012-12-06 16:19:50 -08:00
|
|
|
$entangle_body
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2012-10-15 14:56:42 -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-07-18 16:18:02 -07:00
|
|
|
match params.find(|tpp| tp.ident == tpp.ident) {
|
2012-09-26 17:33:34 -07:00
|
|
|
None => params.push(*tp),
|
2012-08-03 19:59:04 -07:00
|
|
|
_ => ()
|
2012-07-24 18:00:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-08 19:37:25 -08:00
|
|
|
cx.ty_path_ast_builder(path(~[cx.ident_of(~"super"),
|
|
|
|
cx.ident_of(~"__Buffer")], self.span)
|
2012-12-23 17:41:37 -05:00
|
|
|
.add_tys(cx.ty_vars_global(params)))
|
2012-07-24 18:00:08 -07:00
|
|
|
}
|
|
|
|
|
2012-12-06 16:19:50 -08:00
|
|
|
fn gen_buffer_type(cx: ext_ctxt) -> @ast::item {
|
|
|
|
let ext_cx = cx;
|
|
|
|
let mut params: ~[ast::ty_param] = ~[];
|
|
|
|
let fields = do (copy self.states).map_to_vec |s| {
|
|
|
|
for s.ty_params.each |tp| {
|
|
|
|
match params.find(|tpp| tp.ident == tpp.ident) {
|
|
|
|
None => params.push(*tp),
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let ty = s.to_ty(cx);
|
2012-12-23 17:41:37 -05:00
|
|
|
let fty = quote_ty!( ::pipes::Packet<$ty> );
|
2012-12-06 16:19:50 -08:00
|
|
|
|
2012-07-18 16:18:02 -07:00
|
|
|
cx.ty_field_imm(cx.ident_of(s.name), fty)
|
2012-07-24 18:00:08 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
cx.item_ty_poly(
|
2012-07-18 16:18:02 -07:00
|
|
|
cx.ident_of(~"__Buffer"),
|
2012-11-12 19:32:48 -08:00
|
|
|
dummy_sp(),
|
2012-07-24 18:00:08 -07:00
|
|
|
cx.ty_rec(fields),
|
2013-01-28 10:46:43 -08:00
|
|
|
cx.strip_bounds(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-09-26 17:33:34 -07:00
|
|
|
items.push(self.gen_buffer_type(cx))
|
2012-07-23 14:46:39 -07:00
|
|
|
}
|
|
|
|
|
2012-09-26 17:33:34 -07:00
|
|
|
items.push(cx.item_mod(cx.ident_of(~"client"),
|
|
|
|
self.span,
|
|
|
|
client_states));
|
|
|
|
items.push(cx.item_mod(cx.ident_of(~"server"),
|
|
|
|
self.span,
|
|
|
|
server_states));
|
2012-07-05 16:07:53 -07:00
|
|
|
|
2012-07-18 16:18:02 -07:00
|
|
|
cx.item_mod(cx.ident_of(self.name), self.span, items)
|
2012-07-05 16:07:53 -07:00
|
|
|
}
|
2013-01-29 13:54:06 -08:00
|
|
|
}
|