Include spans in var_refs of simplexpr
This commit is contained in:
parent
c20b172662
commit
7abf38cbfc
5 changed files with 39 additions and 23 deletions
|
@ -15,7 +15,7 @@ pub struct StateChangeHandler {
|
||||||
|
|
||||||
impl StateChangeHandler {
|
impl StateChangeHandler {
|
||||||
fn used_variables(&self) -> impl Iterator<Item = &VarName> {
|
fn used_variables(&self) -> impl Iterator<Item = &VarName> {
|
||||||
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.
|
/// Run the StateChangeHandler.
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl Generic {
|
||||||
|
|
||||||
/// returns all the variables that are referenced in this widget
|
/// returns all the variables that are referenced in this widget
|
||||||
pub fn referenced_vars(&self) -> impl Iterator<Item = &VarName> {
|
pub fn referenced_vars(&self) -> impl Iterator<Item = &VarName> {
|
||||||
self.attrs.iter().flat_map(|(_, value)| value.var_refs())
|
self.attrs.iter().flat_map(|(_, value)| value.var_refs()).map(|(_, value)| value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
dynval::{ConversionError, DynVal},
|
dynval::{ConversionError, DynVal},
|
||||||
};
|
};
|
||||||
use eww_shared_util::{Span, Spanned, VarName};
|
use eww_shared_util::{Span, Spanned, VarName};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum EvalError {
|
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::*;
|
use SimplExpr::*;
|
||||||
match self {
|
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(),
|
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) => {
|
BinOp(_, box a, _, box b) | JsonAccess(_, box a, box b) => {
|
||||||
let mut refs = a.var_refs();
|
let mut refs = a.var_refs();
|
||||||
refs.extend(b.var_refs().iter());
|
refs.extend(b.var_refs().iter());
|
||||||
|
@ -141,7 +141,7 @@ impl SimplExpr {
|
||||||
SimplExpr::Concat(span, elems) => {
|
SimplExpr::Concat(span, elems) => {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
for elem in elems {
|
for elem in elems {
|
||||||
let result = elem.eval(values)?;
|
let result = dbg!(elem.eval(values))?;
|
||||||
output.push_str(&result.0);
|
output.push_str(&result.0);
|
||||||
}
|
}
|
||||||
Ok(DynVal(output, *span))
|
Ok(DynVal(output, *span))
|
||||||
|
|
|
@ -10,24 +10,36 @@ pub fn b<T>(x: T) -> Box<T> {
|
||||||
|
|
||||||
pub fn parse_stringlit(
|
pub fn parse_stringlit(
|
||||||
span: Span,
|
span: Span,
|
||||||
segs: Vec<Sp<StrLitSegment>>,
|
mut segs: Vec<Sp<StrLitSegment>>,
|
||||||
) -> Result<SimplExpr, lalrpop_util::ParseError<usize, Token, LexicalError>> {
|
) -> Result<SimplExpr, lalrpop_util::ParseError<usize, Token, LexicalError>> {
|
||||||
let file_id = span.2;
|
let file_id = span.2;
|
||||||
let parser = crate::simplexpr_parser::ExprParser::new();
|
let parser = crate::simplexpr_parser::ExprParser::new();
|
||||||
|
|
||||||
let elems = segs
|
if segs.len() == 1 {
|
||||||
.into_iter()
|
let (lo, seg, hi) = segs.remove(0);
|
||||||
.filter_map(|(lo, segment, hi)| {
|
let span = Span(lo, hi, file_id);
|
||||||
let span = Span(lo, hi, file_id);
|
match seg {
|
||||||
match segment {
|
StrLitSegment::Literal(lit) => Ok(SimplExpr::Literal(DynVal(lit, span))),
|
||||||
StrLitSegment::Literal(lit) if lit.is_empty() => None,
|
StrLitSegment::Interp(toks) => {
|
||||||
StrLitSegment::Literal(lit) => Some(Ok(SimplExpr::Literal(DynVal(lit, span)))),
|
let token_stream = toks.into_iter().map(|x| Ok(x));
|
||||||
StrLitSegment::Interp(toks) => {
|
parser.parse(file_id, token_stream)
|
||||||
let token_stream = toks.into_iter().map(|x| Ok(x));
|
|
||||||
Some(parser.parse(file_id, token_stream))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.collect::<Result<Vec<SimplExpr>, _>>()?;
|
} else {
|
||||||
Ok(SimplExpr::Concat(span, elems))
|
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::<Result<Vec<SimplExpr>, _>>()?;
|
||||||
|
Ok(SimplExpr::Concat(span, elems))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,11 @@ pub fn validate_variables_in_widget_use(
|
||||||
let values = widget.attrs.attrs.values();
|
let values = widget.attrs.attrs.values();
|
||||||
let unknown_var = values.filter_map(|value| value.value.as_simplexpr().ok()).find_map(|expr: SimplExpr| {
|
let unknown_var = values.filter_map(|value| value.value.as_simplexpr().ok()).find_map(|expr: SimplExpr| {
|
||||||
let span = expr.span();
|
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 {
|
if let Some((span, var)) = unknown_var {
|
||||||
return Err(ValidationError::UnknownVariable { span, name: var.clone(), in_definition: is_in_definition });
|
return Err(ValidationError::UnknownVariable { span, name: var.clone(), in_definition: is_in_definition });
|
||||||
|
|
Loading…
Add table
Reference in a new issue