Implement filter transformation

This commit is contained in:
Kogia-sima 2020-07-15 06:13:37 +09:00
parent 2d15165406
commit 373ffc135e
1 changed files with 61 additions and 19 deletions

View File

@ -1,4 +1,5 @@
use proc_macro2::Span; use proc_macro2::Span;
use quote::ToTokens;
use syn::parse::{Parse, ParseStream as SynParseStream, Result as ParseResult}; use syn::parse::{Parse, ParseStream as SynParseStream, Result as ParseResult};
use syn::spanned::Spanned; use syn::spanned::Spanned;
use syn::{BinOp, Block, Expr}; use syn::{BinOp, Block, Expr};
@ -31,7 +32,7 @@ impl Parse for CodeBlock {
let main = s.parse::<Expr>()?; let main = s.parse::<Expr>()?;
let code_block = match main { let code_block = match main {
Expr::Binary(b) if matches!(b.op, BinOp::Or(_)) => { Expr::Binary(b) if matches!(b.op, BinOp::BitOr(_)) => {
match *b.right { match *b.right {
Expr::Call(c) => { Expr::Call(c) => {
if let Expr::Path(ref p) = *c.func { if let Expr::Path(ref p) = *c.func {
@ -123,6 +124,18 @@ struct SourceBuilder {
} }
impl SourceBuilder { impl SourceBuilder {
fn new(escape: bool) -> SourceBuilder {
SourceBuilder {
escape,
source: String::from("{\n"),
source_map: SourceMap::default(),
}
}
fn reserve(&mut self, additional: usize) {
self.source.reserve(additional);
}
fn write_token<'a>(&mut self, token: &Token<'a>) { fn write_token<'a>(&mut self, token: &Token<'a>) {
let entry = SourceMapEntry { let entry = SourceMapEntry {
original: token.offset(), original: token.offset(),
@ -156,16 +169,12 @@ impl SourceBuilder {
escape: bool, escape: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
// parse and split off filter // parse and split off filter
let code_block = syn::parse_str::<CodeBlock>(token.as_str()).map_err(|e| e)?; let code_block = syn::parse_str::<CodeBlock>(token.as_str()).map_err(|e| {
let span = e.span();
if let Some(filter) = code_block.filter { let mut err = make_error!(ErrorKind::RustSyntaxError(e));
let mut err = make_error!(ErrorKind::Unimplemented( err.offset = into_offset(token.as_str(), span).map(|p| token.offset() + p);
"Filter is not implemented".to_owned() err
)); })?;
err.offset = into_offset(token.as_str(), filter.span());
return Err(err);
}
let method = if self.escape && escape { let method = if self.escape && escape {
"render_escaped" "render_escaped"
} else { } else {
@ -175,8 +184,46 @@ impl SourceBuilder {
self.source.push_str("__sf_rt::"); self.source.push_str("__sf_rt::");
self.source.push_str(method); self.source.push_str(method);
self.source.push_str("!(__sf_buf, "); self.source.push_str("!(__sf_buf, ");
self.write_token(token);
if let Some(filter) = code_block.filter {
let expr_str = code_block.expr.into_token_stream().to_string();
let (name, extra_args) = match filter {
Filter::Ident(i) => (i.to_string(), None),
Filter::Call(c) => (
c.func.into_token_stream().to_string(),
Some(c.args.into_token_stream().to_string()),
),
};
self.source.push_str("sailfish::runtime::filter::");
self.source.push_str(&*name);
self.source.push_str("(");
// arguments to filter function
{
self.source.push_str("&(");
let entry = SourceMapEntry {
original: token.offset(),
new: self.source.len(),
length: expr_str.len(),
};
self.source_map.entries.push(entry);
self.source.push_str(&expr_str);
self.source.push_str(")");
if let Some(extra_args) = extra_args {
self.source.push_str(", ");
self.source.push_str(&*extra_args);
}
}
self.source.push_str(")");
} else {
self.write_token(token);
}
self.source.push_str(");\n"); self.source.push_str(");\n");
Ok(()) Ok(())
} }
@ -286,13 +333,8 @@ impl Translator {
) -> Result<TranslatedSource, Error> { ) -> Result<TranslatedSource, Error> {
let original_source = token_iter.original_source; let original_source = token_iter.original_source;
let mut source = String::with_capacity(original_source.len()); let mut ps = SourceBuilder::new(self.escape);
source.push_str("{\n"); ps.reserve(original_source.len());
let mut ps = SourceBuilder {
escape: self.escape,
source,
source_map: SourceMap::default(),
};
ps.feed_tokens(token_iter)?; ps.feed_tokens(token_iter)?;
Ok(ps.finalize()?) Ok(ps.finalize()?)