use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span, respan};
use syntax::ptr::P;
use ident::ToIdent;
use invoke::{Invoke, Identity};
use ty::TyBuilder;
pub struct FnDeclBuilder<F=Identity> {
callback: F,
span: Span,
args: Vec<ast::Arg>,
variadic: bool,
}
impl FnDeclBuilder {
pub fn new() -> FnDeclBuilder {
FnDeclBuilder::new_with_callback(Identity)
}
}
impl<F> FnDeclBuilder<F>
where F: Invoke<P<ast::FnDecl>>,
{
pub fn new_with_callback(callback: F) -> Self {
FnDeclBuilder {
callback: callback,
span: DUMMY_SP,
args: Vec::new(),
variadic: false,
}
}
pub fn span(mut self, span: Span) -> Self {
self.span = span;
self
}
pub fn variadic(mut self) -> Self {
self.variadic = true;
self
}
pub fn with_arg(mut self, arg: ast::Arg) -> Self {
self.args.push(arg);
self
}
pub fn arg<I>(self, id: I) -> ArgBuilder<Self>
where I: ToIdent,
{
ArgBuilder::new_with_callback(id, self)
}
pub fn no_return(self) -> F::Result {
let ret_ty = ast::FunctionRetTy::NoReturn(self.span);
self.build(ret_ty)
}
pub fn build_output(self, ty: P<ast::Ty>) -> F::Result {
self.build(ast::FunctionRetTy::Return(ty))
}
pub fn output(self) -> TyBuilder<Self> {
TyBuilder::new_with_callback(self)
}
pub fn build(self, output: ast::FunctionRetTy) -> F::Result {
self.callback.invoke(P(ast::FnDecl {
inputs: self.args,
output: output,
variadic: self.variadic,
}))
}
}
impl<F> Invoke<ast::Arg> for FnDeclBuilder<F>
where F: Invoke<P<ast::FnDecl>>
{
type Result = Self;
fn invoke(self, arg: ast::Arg) -> Self {
self.with_arg(arg)
}
}
impl<F> Invoke<P<ast::Ty>> for FnDeclBuilder<F>
where F: Invoke<P<ast::FnDecl>>,
{
type Result = F::Result;
fn invoke(self, ty: P<ast::Ty>) -> F::Result {
self.build_output(ty)
}
}
pub struct ArgBuilder<F=Identity> {
callback: F,
span: Span,
id: ast::Ident,
}
impl ArgBuilder {
pub fn new<I>(id: I) -> Self where I: ToIdent {
ArgBuilder::new_with_callback(id, Identity)
}
}
impl<F> ArgBuilder<F>
where F: Invoke<ast::Arg>,
{
pub fn new_with_callback<I>(id: I, callback: F) -> ArgBuilder<F>
where I: ToIdent,
{
ArgBuilder {
callback: callback,
span: DUMMY_SP,
id: id.to_ident(),
}
}
pub fn span(mut self, span: Span) -> Self {
self.span = span;
self
}
pub fn build_ty(self, ty: P<ast::Ty>) -> F::Result {
let path = respan(self.span, self.id);
self.callback.invoke(ast::Arg {
id: ast::DUMMY_NODE_ID,
ty: ty,
pat: P(ast::Pat {
id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(
ast::BindByValue(ast::Mutability::MutImmutable),
path,
None,
),
span: self.span,
}),
})
}
pub fn ty(self) -> TyBuilder<ArgTyBuilder<F>> {
TyBuilder::new_with_callback(ArgTyBuilder(self))
}
}
pub struct ArgTyBuilder<F>(ArgBuilder<F>);
impl<F: Invoke<ast::Arg>> Invoke<P<ast::Ty>> for ArgTyBuilder<F>
{
type Result = F::Result;
fn invoke(self, ty: P<ast::Ty>) -> F::Result {
self.0.build_ty(ty)
}
}