aboutsummaryrefslogtreecommitdiffstats
path: root/askama_shared/src/generator.rs
diff options
context:
space:
mode:
authorLibravatar René Kijewski <kijewski@library.vetmed.fu-berlin.de>2021-07-17 13:40:49 +0200
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2021-07-30 11:45:56 +0200
commit268d8250fb0a9cdcbbd760bdf39424ed02fd1920 (patch)
tree02a31fa920a29cff2420e597158637619cf7606c /askama_shared/src/generator.rs
parent1622df7aeecb71fca2da630330513b26cefef16b (diff)
downloadaskama-268d8250fb0a9cdcbbd760bdf39424ed02fd1920.tar.gz
askama-268d8250fb0a9cdcbbd760bdf39424ed02fd1920.tar.bz2
askama-268d8250fb0a9cdcbbd760bdf39424ed02fd1920.zip
Use "target()" to parse "when" block
`target()` as used in parsing "let" and "if let" implements parsing nested tuples and structs. But it does not implement parsing literals. The functions `match_variant()` and `with_parameters()` as used in parsing "when" blocks do not implement parsing nested structs, but it implements parsing literals. This PR combines `match_variant()` and `with_parameters()` into `target()`, so that all `{%when%}` support nested structs, too.
Diffstat (limited to 'askama_shared/src/generator.rs')
-rw-r--r--askama_shared/src/generator.rs144
1 files changed, 42 insertions, 102 deletions
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index 36d1841..dccda93 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -2,10 +2,7 @@ use super::{get_template_source, CompileError, Integrations};
use crate::filters;
use crate::heritage::{Context, Heritage};
use crate::input::{Source, TemplateInput};
-use crate::parser::{
- parse, Cond, CondTest, Expr, MatchParameter, MatchParameters, MatchVariant, Node, Target, When,
- Ws,
-};
+use crate::parser::{parse, Cond, CondTest, Expr, Node, Target, When, Ws};
use proc_macro2::Span;
@@ -498,14 +495,11 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
buf.write("} else if ");
}
- if let Some((variant, params)) = target {
+ if let Some(target) = target {
let mut expr_buf = Buffer::new(0);
self.visit_expr(&mut expr_buf, expr)?;
buf.write("let ");
- self.visit_match_variant(buf, variant);
- if let Some(params) = params {
- self.visit_match_params(buf, params);
- }
+ self.visit_target(buf, true, true, target);
buf.write(" = &(");
buf.write(&expr_buf.buf);
buf.write(")");
@@ -562,7 +556,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
let mut arm_size = 0;
for (i, arm) in arms.iter().enumerate() {
- let &(ws, ref variant, ref params, ref body) = arm;
+ let &(ws, ref target, ref body) = arm;
self.handle_ws(ws);
if i > 0 {
@@ -573,14 +567,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
}
self.locals.push();
- match *variant {
- Some(ref param) => {
- self.visit_match_variant(buf, param);
- }
- None => buf.write("_"),
- };
-
- self.visit_match_params(buf, params);
+ self.visit_target(buf, true, true, target);
buf.writeln(" => {")?;
arm_size = self.handle(ctx, body, buf, AstLevel::Nested)?;
@@ -614,7 +601,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
let flushed = self.write_buf_writable(buf)?;
buf.write("for (");
- self.visit_target(buf, true, var);
+ self.visit_target(buf, true, true, var);
match iter {
Expr::Range(_, _, _) => buf.writeln(&format!(
", _loop_item) in ::askama::helpers::TemplateLoop::new({}) {{",
@@ -807,7 +794,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
self.handle_ws(ws);
self.write_buf_writable(buf)?;
buf.write("let ");
- self.visit_target(buf, false, var);
+ self.visit_target(buf, false, true, var);
buf.writeln(";")
}
@@ -830,6 +817,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
Target::Struct(_, named_targets) => named_targets
.iter()
.any(|(_, target)| self.is_shadowing_variable(target)),
+ _ => panic!("Cannot have literals on the left-hand-side of an assignment."),
}
}
@@ -857,7 +845,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
buf.write("let ");
}
- self.visit_target(buf, true, var);
+ self.visit_target(buf, true, true, var);
buf.writeln(&format!(" = {};", &expr_buf.buf))
}
@@ -1082,84 +1070,6 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
DisplayWrap::Unwrapped
}
- fn visit_match_variant(&mut self, buf: &mut Buffer, param: &MatchVariant<'_>) -> DisplayWrap {
- let mut expr_buf = Buffer::new(0);
- let wrapped = match *param {
- MatchVariant::StrLit(s) => {
- expr_buf.write("&");
- self.visit_str_lit(&mut expr_buf, s)
- }
- MatchVariant::CharLit(s) => self.visit_char_lit(&mut expr_buf, s),
- MatchVariant::NumLit(s) => self.visit_num_lit(&mut expr_buf, s),
- MatchVariant::Name(s) => {
- expr_buf.write(s);
- DisplayWrap::Unwrapped
- }
- MatchVariant::Path(ref s) => {
- expr_buf.write(&s.join("::"));
- DisplayWrap::Unwrapped
- }
- };
- buf.write(&expr_buf.buf);
- wrapped
- }
-
- fn visit_match_param(&mut self, buf: &mut Buffer, param: &MatchParameter<'_>) -> DisplayWrap {
- let mut expr_buf = Buffer::new(0);
- let wrapped = match *param {
- MatchParameter::NumLit(s) => self.visit_num_lit(&mut expr_buf, s),
- MatchParameter::StrLit(s) => self.visit_str_lit(&mut expr_buf, s),
- MatchParameter::CharLit(s) => self.visit_char_lit(&mut expr_buf, s),
- MatchParameter::Name(s) => {
- expr_buf.write(s);
- DisplayWrap::Unwrapped
- }
- };
- buf.write(&expr_buf.buf);
- wrapped
- }
-
- fn visit_match_params(&mut self, buf: &mut Buffer, params: &MatchParameters<'a>) {
- match params {
- MatchParameters::Simple(params) => {
- if !params.is_empty() {
- buf.write("(");
- for (i, param) in params.iter().enumerate() {
- if let MatchParameter::Name(p) = *param {
- self.locals.insert_with_default(p);
- }
- if i > 0 {
- buf.write(", ");
- }
- self.visit_match_param(buf, param);
- }
- buf.write(")");
- }
- }
- MatchParameters::Named(params) => {
- buf.write("{");
- for (i, param) in params.iter().enumerate() {
- if let Some(MatchParameter::Name(p)) = param.1 {
- let p = normalize_identifier(p);
- self.locals.insert_with_default(p);
- } else {
- self.locals.insert_with_default(param.0);
- }
-
- if i > 0 {
- buf.write(", ");
- }
- buf.write(param.0);
- if let Some(param) = &param.1 {
- buf.write(":");
- self.visit_match_param(buf, param);
- }
- }
- buf.write("}");
- }
- }
- }
-
fn visit_filter(
&mut self,
buf: &mut Buffer,
@@ -1514,8 +1424,17 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
DisplayWrap::Unwrapped
}
- fn visit_target(&mut self, buf: &mut Buffer, initialized: bool, target: &Target<'a>) {
+ fn visit_target(
+ &mut self,
+ buf: &mut Buffer,
+ initialized: bool,
+ first_level: bool,
+ target: &Target<'a>,
+ ) {
match target {
+ Target::Name("_") => {
+ buf.write("_");
+ }
Target::Name(name) => {
let name = normalize_identifier(name);
match initialized {
@@ -1528,7 +1447,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
buf.write(&path.join("::"));
buf.write("(");
for target in targets {
- self.visit_target(buf, initialized, target);
+ self.visit_target(buf, initialized, false, target);
buf.write(",");
}
buf.write(")");
@@ -1539,11 +1458,32 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
for (name, target) in targets {
buf.write(normalize_identifier(name));
buf.write(": ");
- self.visit_target(buf, initialized, target);
+ self.visit_target(buf, initialized, false, target);
buf.write(",");
}
buf.write(" }");
}
+ Target::Path(path) => {
+ self.visit_path(buf, path);
+ }
+ Target::StrLit(s) => {
+ if first_level {
+ buf.write("&");
+ }
+ self.visit_str_lit(buf, s);
+ }
+ Target::NumLit(s) => {
+ if first_level {
+ buf.write("&");
+ }
+ self.visit_num_lit(buf, s);
+ }
+ Target::CharLit(s) => {
+ if first_level {
+ buf.write("&");
+ }
+ self.visit_char_lit(buf, s);
+ }
}
}