From 7abf38cbfca5a01395af1adf2e2b0b174803d321 Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Tue, 17 Aug 2021 11:53:45 +0200 Subject: [PATCH] Include spans in var_refs of simplexpr --- crates/eww/src/eww_state.rs | 2 +- crates/eww/src/widgets/widget_node.rs | 2 +- crates/simplexpr/src/eval.rs | 10 ++--- .../simplexpr/src/parser/lalrpop_helpers.rs | 42 ++++++++++++------- crates/yuck/src/config/validate.rs | 6 ++- 5 files changed, 39 insertions(+), 23 deletions(-) diff --git a/crates/eww/src/eww_state.rs b/crates/eww/src/eww_state.rs index 5ea82e5..7bba210 100644 --- a/crates/eww/src/eww_state.rs +++ b/crates/eww/src/eww_state.rs @@ -15,7 +15,7 @@ pub struct StateChangeHandler { impl StateChangeHandler { fn used_variables(&self) -> impl Iterator { - self.unresolved_values.iter().flat_map(|(_, value)| value.var_refs()) + self.unresolved_values.iter().flat_map(|(_, value)| value.var_refs()).map(|(_, value)| value) } /// Run the StateChangeHandler. diff --git a/crates/eww/src/widgets/widget_node.rs b/crates/eww/src/widgets/widget_node.rs index 08740d5..70d36a4 100644 --- a/crates/eww/src/widgets/widget_node.rs +++ b/crates/eww/src/widgets/widget_node.rs @@ -80,7 +80,7 @@ impl Generic { /// returns all the variables that are referenced in this widget pub fn referenced_vars(&self) -> impl Iterator { - self.attrs.iter().flat_map(|(_, value)| value.var_refs()) + self.attrs.iter().flat_map(|(_, value)| value.var_refs()).map(|(_, value)| value) } } diff --git a/crates/simplexpr/src/eval.rs b/crates/simplexpr/src/eval.rs index e3a347e..13ba3f4 100644 --- a/crates/simplexpr/src/eval.rs +++ b/crates/simplexpr/src/eval.rs @@ -5,7 +5,7 @@ use crate::{ dynval::{ConversionError, DynVal}, }; use eww_shared_util::{Span, Spanned, VarName}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; #[derive(Debug, thiserror::Error)] pub enum EvalError { @@ -102,12 +102,12 @@ impl SimplExpr { }) } - pub fn var_refs(&self) -> HashSet<&VarName> { + pub fn var_refs(&self) -> Vec<(Span, &VarName)> { use SimplExpr::*; match self { - Literal(..) => HashSet::new(), + Literal(..) => Vec::new(), + VarRef(span, name) => vec![(*span, name)], Concat(_, elems) => elems.iter().flat_map(|x| x.var_refs().into_iter()).collect(), - VarRef(_, name) => maplit::hashset! { name }, BinOp(_, box a, _, box b) | JsonAccess(_, box a, box b) => { let mut refs = a.var_refs(); refs.extend(b.var_refs().iter()); @@ -141,7 +141,7 @@ impl SimplExpr { SimplExpr::Concat(span, elems) => { let mut output = String::new(); for elem in elems { - let result = elem.eval(values)?; + let result = dbg!(elem.eval(values))?; output.push_str(&result.0); } Ok(DynVal(output, *span)) diff --git a/crates/simplexpr/src/parser/lalrpop_helpers.rs b/crates/simplexpr/src/parser/lalrpop_helpers.rs index 4815872..fd7a1a2 100644 --- a/crates/simplexpr/src/parser/lalrpop_helpers.rs +++ b/crates/simplexpr/src/parser/lalrpop_helpers.rs @@ -10,24 +10,36 @@ pub fn b(x: T) -> Box { pub fn parse_stringlit( span: Span, - segs: Vec>, + mut segs: Vec>, ) -> Result> { let file_id = span.2; let parser = crate::simplexpr_parser::ExprParser::new(); - let elems = segs - .into_iter() - .filter_map(|(lo, segment, hi)| { - let span = Span(lo, hi, file_id); - match segment { - StrLitSegment::Literal(lit) if lit.is_empty() => None, - StrLitSegment::Literal(lit) => Some(Ok(SimplExpr::Literal(DynVal(lit, span)))), - StrLitSegment::Interp(toks) => { - let token_stream = toks.into_iter().map(|x| Ok(x)); - Some(parser.parse(file_id, token_stream)) - } + if segs.len() == 1 { + let (lo, seg, hi) = segs.remove(0); + let span = Span(lo, hi, file_id); + match seg { + StrLitSegment::Literal(lit) => Ok(SimplExpr::Literal(DynVal(lit, span))), + StrLitSegment::Interp(toks) => { + let token_stream = toks.into_iter().map(|x| Ok(x)); + parser.parse(file_id, token_stream) } - }) - .collect::, _>>()?; - Ok(SimplExpr::Concat(span, elems)) + } + } else { + let elems = segs + .into_iter() + .filter_map(|(lo, segment, hi)| { + let span = Span(lo, hi, file_id); + match segment { + StrLitSegment::Literal(lit) if lit.is_empty() => None, + StrLitSegment::Literal(lit) => Some(Ok(SimplExpr::Literal(DynVal(lit, span)))), + StrLitSegment::Interp(toks) => { + let token_stream = toks.into_iter().map(|x| Ok(x)); + Some(parser.parse(file_id, token_stream)) + } + } + }) + .collect::, _>>()?; + Ok(SimplExpr::Concat(span, elems)) + } } diff --git a/crates/yuck/src/config/validate.rs b/crates/yuck/src/config/validate.rs index 8a3818b..309b806 100644 --- a/crates/yuck/src/config/validate.rs +++ b/crates/yuck/src/config/validate.rs @@ -87,7 +87,11 @@ pub fn validate_variables_in_widget_use( let values = widget.attrs.attrs.values(); let unknown_var = values.filter_map(|value| value.value.as_simplexpr().ok()).find_map(|expr: SimplExpr| { let span = expr.span(); - expr.var_refs().iter().map(move |&x| (span, x.clone())).find(|(span, var_ref)| !variables.contains(var_ref)) + expr.var_refs() + .iter() + .cloned() + .map(|(span, var_ref)| (span, var_ref.clone())) + .find(|(_, var_ref)| !variables.contains(var_ref)) }); if let Some((span, var)) = unknown_var { return Err(ValidationError::UnknownVariable { span, name: var.clone(), in_definition: is_in_definition });