diff options
| author | Eric Holk <eric.holk@gmail.com> | 2012-07-23 18:50:53 -0700 |
|---|---|---|
| committer | Eric Holk <eric.holk@gmail.com> | 2012-07-25 12:12:25 -0700 |
| commit | 7f5f1f90a06961b769162c437681194900ef3b7e (patch) | |
| tree | e8ccac02944c70bfe397bfdb8c08370f7a585013 /src/libsyntax | |
| parent | b97fe9835430553c0b566cf1f5687e6c7403821b (diff) | |
Compiled a bounded version of pingpong.
There are some failures in the other pipe tests, but these seem to just be a matter of generalizing the library code. Updating pipes library so all tests pass again
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/pipes/ast_builder.rs | 73 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/pipec.rs | 183 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/proto.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/parse.rs | 12 |
4 files changed, 244 insertions, 43 deletions
diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index c03b5e28adc..b70100de4c5 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -7,6 +7,14 @@ import ast::{ident, node_id}; import codemap::span; import ext::base::mk_ctxt; +// Transitional reexports so qquote can find the paths it is looking for +mod syntax { + import ext; + export ext; + import parse; + export parse; +} + fn ident(s: ~str) -> ast::ident { @(copy s) } @@ -93,9 +101,60 @@ trait ext_ctxt_ast_builder { fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty]; fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field; fn ty_rec(+~[ast::ty_field]) -> @ast::ty; + fn field_imm(name: ident, e: @ast::expr) -> ast::field; + fn rec(+~[ast::field]) -> @ast::expr; + fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk; + 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; } impl ast_builder of ext_ctxt_ast_builder for ext_ctxt { + 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()} + } + + fn stmt_expr(e: @ast::expr) -> @ast::stmt { + @{node: ast::stmt_expr(e, self.next_id()), + span: empty_span()} + } + + fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt { + // If the quasiquoter could interpolate idents, this is all + // we'd need. + // + //let ext_cx = self; + //#ast[stmt] { let $(ident) = $(e) } + + @{node: ast::stmt_decl(@{node: ast::decl_local(~[ + @{node: {is_mutbl: false, + ty: self.ty_infer(), + pat: @{id: self.next_id(), + node: ast::pat_ident(path(ident), none), + span: 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()} + } + + fn field_imm(name: ident, e: @ast::expr) -> ast::field { + {node: {mutbl: ast::m_imm, ident: name, expr: e}, + span: 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()} + } + 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()} @@ -107,6 +166,12 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt { span: empty_span()} } + fn ty_infer() -> @ast::ty { + @{id: self.next_id(), + node: ast::ty_infer, + span: empty_span()} + } + fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound]) -> ast::ty_param { @@ -128,9 +193,9 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt { id: self.next_id()} } - fn expr_block(e: @ast::expr) -> ast::blk { + fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk { let blk = {view_items: ~[], - stmts: ~[], + stmts: stmts, expr: some(e), id: self.next_id(), rules: ast::default_blk}; @@ -139,6 +204,10 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt { span: empty_span()} } + fn expr_block(e: @ast::expr) -> ast::blk { + self.block(~[], e) + } + fn fn_decl(+inputs: ~[ast::arg], output: @ast::ty) -> ast::fn_decl { {inputs: inputs, diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 849c3a39efe..7dd33e35bc8 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -23,6 +23,14 @@ import ast_builder::methods; import ast_builder::path; import ast_builder::path_concat; +// Transitional reexports so qquote can find the paths it is looking for +mod syntax { + import ext; + export ext; + import parse; + export parse; +} + trait gen_send { fn gen_send(cx: ext_ctxt) -> @ast::item; } @@ -60,14 +68,34 @@ impl compile of gen_send for message { ast::by_copy)], args_ast); - let pat = alt (this.dir, next.dir) { - (send, send) { ~"(c, s)" } - (send, recv) { ~"(s, c)" } - (recv, send) { ~"(s, c)" } - (recv, recv) { ~"(c, s)" } - }; + let mut body = ~"{\n"; + + if this.proto.is_bounded() { + let (sp, rp) = alt (this.dir, next.dir) { + (send, send) { ("c", "s") } + (send, recv) { ("s", "c") } + (recv, send) { ("s", "c") } + (recv, recv) { ("c", "s") } + }; - let mut body = #fmt("{ let %s = pipes::entangle();\n", pat); + body += "let b = pipe.reuse_buffer();\n"; + body += #fmt("let %s = pipes::send_packet_buffered(\ + ptr::addr_of(b.buffer.data.%s));\n", + sp, *next.name); + body += #fmt("let %s = pipes::recv_packet_buffered(\ + ptr::addr_of(b.buffer.data.%s));\n", + rp, *next.name); + } + else { + let pat = alt (this.dir, next.dir) { + (send, send) { ~"(c, s)" } + (send, recv) { ~"(s, c)" } + (recv, send) { ~"(s, c)" } + (recv, recv) { ~"(c, s)" } + }; + + body += #fmt("let %s = pipes::entangle();\n", pat); + } body += #fmt("let message = %s::%s(%s);\n", *this.proto.name, *self.name(), @@ -189,42 +217,121 @@ impl compile of to_type_decls for state { } } - vec::push(items, - cx.item_ty_poly( - self.data_name(), - 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)); + if !self.proto.is_bounded() { + vec::push(items, + cx.item_ty_poly( + self.data_name(), + 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 { + let ext_cx = cx; + vec::push(items, + cx.item_ty_poly( + self.data_name(), + 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))), + #ast[ty] { buffer }])), + self.ty_params)); + }; items } } impl compile of gen_init for protocol { fn gen_init(cx: ext_ctxt) -> @ast::item { + let ext_cx = cx; + #debug("gen_init"); let start_state = self.states[0]; - let body = alt start_state.dir { - send { cx.parse_expr(~"pipes::entangle()") } - recv { - cx.parse_expr(~"{ \ - let (s, c) = pipes::entangle(); \ - (c, s) \ - }") - } + let body = if !self.is_bounded() { + alt start_state.dir { + send { #ast { pipes::entangle() } } + recv { + #ast {{ + let (s, c) = pipes::entangle(); + (c, s) + }} + } + } + } + else { + let body = self.gen_init_bounded(ext_cx); + alt start_state.dir { + send { body } + recv { + #ast {{ + let (s, c) = $(body); + (c, s) + }} + } + } }; cx.parse_item(#fmt("fn init%s() -> (client::%s, server::%s)\ - { %s }", + { import pipes::has_buffer; %s }", start_state.ty_params.to_source(), start_state.to_ty(cx).to_source(), start_state.to_ty(cx).to_source(), body.to_source())) } + 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)); + ext_cx.field_imm(s.name, #ast { pipes::mk_packet::<$(fty)>() }) + })) + } + + 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::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( + #fmt("data.%s.set_buffer(buffer)", *s.name))), + ext_cx.parse_expr( + #fmt("ptr::addr_of(data.%s)", *self.states[0].name)))); + + #ast {{ + let buffer = $(buffer); + do pipes::entangle_buffer(buffer) |buffer, data| { + $(entangle_body) + } + }} + } + + fn gen_buffer_type(cx: ext_ctxt) -> @ast::item { + let ext_cx = cx; + cx.item_ty( + @~"buffer", + cx.ty_rec( + (copy self.states).map_to_vec( + |s| { + let ty = cx.ty_path_ast_builder(path(s.name)); + let fty = #ast[ty] { + pipes::packet<$(ty)> + }; + cx.ty_field_imm(s.name, fty) + }))) + } + fn compile(cx: ext_ctxt) -> @ast::item { let mut items = ~[self.gen_init(cx)]; let mut client_states = ~[]; @@ -239,20 +346,7 @@ impl compile of gen_init for protocol { } if self.is_bounded() { - vec::push( - items, - cx.item_ty( - @~"buffer", - cx.ty_rec( - (copy self.states).map_to_vec( - |s| cx.ty_field_imm( - s.name, - cx.ty_path_ast_builder( - (path(@~"pipes") - + @~"packet") - .add_ty( - cx.ty_path_ast_builder( - path(s.name))))))))) + vec::push(items, self.gen_buffer_type(cx)) } vec::push(items, @@ -310,6 +404,7 @@ impl of to_source for @ast::expr { 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; } impl parse_utils of ext_ctxt_parse_utils for ext_ctxt { @@ -330,6 +425,15 @@ impl parse_utils of ext_ctxt_parse_utils for ext_ctxt { } } + 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***", @@ -338,4 +442,3 @@ impl parse_utils of ext_ctxt_parse_utils for ext_ctxt { self.parse_sess()) } } - diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index 8a535e85188..a0091806b02 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -131,7 +131,24 @@ class protocol_ { fn num_states() -> uint { self.states.len() } - fn is_bounded() -> bool { self.bounded.get() } + fn has_ty_params() -> bool { + for self.states.each |s| { + if s.ty_params.len() > 0 { + ret true; + } + } + false + } + 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 } + } } impl methods for protocol { diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs index 9d56754e5d4..39f4654a138 100644 --- a/src/libsyntax/parse.rs +++ b/src/libsyntax/parse.rs @@ -10,6 +10,7 @@ export new_parser_from_tt; export parse_crate_from_file, parse_crate_from_crate_file; export parse_crate_from_source_str; export parse_expr_from_source_str, parse_item_from_source_str; +export parse_stmt_from_source_str; export parse_from_source_str; import parser::parser; @@ -129,6 +130,17 @@ fn parse_item_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg, ret r; } +fn parse_stmt_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg, + +attrs: ~[ast::attribute], + sess: parse_sess) -> @ast::stmt { + let (p, rdr) = new_parser_etc_from_source_str(sess, cfg, name, + codemap::fss_none, source); + let r = p.parse_stmt(attrs); + sess.chpos = rdr.chpos; + sess.byte_pos = sess.byte_pos + rdr.pos; + ret r; +} + fn parse_from_source_str<T>(f: fn (p: parser) -> T, name: ~str, ss: codemap::file_substr, source: @~str, cfg: ast::crate_cfg, |
