From 09573ea8cf6441b41cac00690dba98f687185d26 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 6 Dec 2012 16:19:50 -0800 Subject: [PATCH] syntax: stage0-guard uses of #ast, rewrite as quote_foo! in stage1,2. --- src/libsyntax/ext/pipes/ast_builder.rs | 9 ++ src/libsyntax/ext/pipes/pipec.rs | 210 +++++++++++++------------ 2 files changed, 122 insertions(+), 97 deletions(-) diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 7293438ca09..7e5a267c008 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -17,6 +17,7 @@ use ast::{ident, node_id}; use ast_util::{ident_to_path, respan, dummy_sp}; use codemap::span; use ext::base::mk_ctxt; +use quote::rt::*; // Transitional reexports so qquote can find the paths it is looking for mod syntax { @@ -121,6 +122,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { span: dummy_sp()} } + #[cfg(stage0)] fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt { // If the quasiquoter could interpolate idents, this is all // we'd need. @@ -142,6 +144,13 @@ impl ext_ctxt: ext_ctxt_ast_builder { span: dummy_sp()}]), span: dummy_sp()}, self.next_id()), span: dummy_sp()} + } + + #[cfg(stage1)] + #[cfg(stage2)] + fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt { + let ext_cx = self; + quote_stmt!( let $ident = $e; ) } fn field_imm(name: ident, e: @ast::expr) -> ast::field { diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 1c4dd197105..822480f0ad6 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -17,12 +17,10 @@ use dvec::DVec; use ast::ident; use ast_util::dummy_sp; use util::interner; -use print::pprust; -use pprust::{item_to_str, ty_to_str}; -use ext::base::{mk_ctxt, ext_ctxt}; +use ext::base::ext_ctxt; use parse::*; use proto::*; - +use quote::rt::*; use ast_builder::{append_types, path}; // Transitional reexports so qquote can find the paths it is looking for @@ -303,6 +301,8 @@ impl state: to_type_decls { } impl protocol: gen_init { + + #[cfg(stage0)] fn gen_init(cx: ext_ctxt) -> @ast::item { let ext_cx = cx; @@ -341,6 +341,47 @@ impl protocol: gen_init { body.to_source(cx))) } + #[cfg(stage1)] + #[cfg(stage2)] + 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 { + send => quote_expr!( pipes::entangle() ), + recv => { + quote_expr!({ + let (s, c) = pipes::entangle(); + (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))) + } + + #[cfg(stage0)] 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); @@ -349,10 +390,22 @@ impl protocol: gen_init { })) } + #[cfg(stage1)] + #[cfg(stage2)] + 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!( + pipes::mk_packet::<$fty>() + )) + })) + } + + #[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 = #ast { ~{header: pipes::BufferHeader(), data: $(buffer_fields)} @@ -376,6 +429,34 @@ impl protocol: gen_init { }} } + #[cfg(stage1)] + #[cfg(stage2)] + 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 + } + }) + } + fn buffer_ty_path(cx: ext_ctxt) -> @ast::Ty { let mut params: ~[ast::ty_param] = ~[]; for (copy self.states).each |s| { @@ -391,6 +472,7 @@ impl protocol: gen_init { .add_tys(cx.ty_vars(params))) } + #[cfg(stage0)] fn gen_buffer_type(cx: ext_ctxt) -> @ast::item { let ext_cx = cx; let mut params: ~[ast::ty_param] = ~[]; @@ -405,6 +487,32 @@ impl protocol: gen_init { let fty = #ast[ty] { pipes::Packet<$(ty)> }; + + cx.ty_field_imm(cx.ident_of(s.name), fty) + }; + + cx.item_ty_poly( + cx.ident_of(~"__Buffer"), + dummy_sp(), + cx.ty_rec(fields), + params) + } + + #[cfg(stage1)] + #[cfg(stage2)] + 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); + let fty = quote_ty!( pipes::Packet<$ty> ); + cx.ty_field_imm(cx.ident_of(s.name), fty) }; @@ -420,7 +528,6 @@ impl protocol: gen_init { let mut client_states = ~[]; let mut server_states = ~[]; - // :( for (copy self.states).each |s| { items += s.to_type_decls(cx); @@ -441,95 +548,4 @@ impl protocol: gen_init { cx.item_mod(cx.ident_of(self.name), self.span, items) } -} - -trait to_source { - // Takes a thing and generates a string containing rust code for it. - fn to_source(cx: ext_ctxt) -> ~str; -} - -impl @ast::item: to_source { - fn to_source(cx: ext_ctxt) -> ~str { - item_to_str(self, cx.parse_sess().interner) } -} - -impl ~[@ast::item]: to_source { - fn to_source(cx: ext_ctxt) -> ~str { - str::connect(self.map(|i| i.to_source(cx)), ~"\n\n") - } -} - -impl @ast::Ty: to_source { - fn to_source(cx: ext_ctxt) -> ~str { - ty_to_str(self, cx.parse_sess().interner) - } -} - -impl ~[@ast::Ty]: to_source { - fn to_source(cx: ext_ctxt) -> ~str { - str::connect(self.map(|i| i.to_source(cx)), ~", ") - } -} - -impl ~[ast::ty_param]: to_source { - fn to_source(cx: ext_ctxt) -> ~str { - pprust::typarams_to_str(self, cx.parse_sess().interner) - } -} - -impl @ast::expr: to_source { - fn to_source(cx: ext_ctxt) -> ~str { - pprust::expr_to_str(self, cx.parse_sess().interner) - } -} - -trait ext_ctxt_parse_utils { - fn parse_item(s: ~str) -> @ast::item; - fn parse_expr(s: ~str) -> @ast::expr; - fn parse_stmt(s: ~str) -> @ast::stmt; - fn parse_tts(s: ~str) -> ~[ast::token_tree]; -} - -impl ext_ctxt: ext_ctxt_parse_utils { - fn parse_item(s: ~str) -> @ast::item { - let res = parse::parse_item_from_source_str( - ~"***protocol expansion***", - @(copy s), - self.cfg(), - ~[], - self.parse_sess()); - match res { - Some(ast) => ast, - None => { - error!("Parse error with ```\n%s\n```", s); - fail - } - } - } - - fn parse_stmt(s: ~str) -> @ast::stmt { - parse::parse_stmt_from_source_str( - ~"***protocol expansion***", - @(copy s), - self.cfg(), - ~[], - self.parse_sess()) - } - - fn parse_expr(s: ~str) -> @ast::expr { - parse::parse_expr_from_source_str( - ~"***protocol expansion***", - @(copy s), - self.cfg(), - self.parse_sess()) - } - - fn parse_tts(s: ~str) -> ~[ast::token_tree] { - parse::parse_tts_from_source_str( - ~"***protocol expansion***", - @(copy s), - self.cfg(), - self.parse_sess()) - } -}