pub struct SpannedExpr<'src> {
pub origin: Origin<'src>,
pub inner: Expr<'src>,
}Expand description
An expression along with its source origin (span and unparsed form).
An expression’s span covers exactly the bytes the expression was parsed from, with no surrounding whitespace. A parenthesized expression includes its parentheses, so every span is a balanced, self-contained slice of the source.
NOTE: SpannedExpr has a manual PartialEq implementation that only considers
the underlying expression, not the span. In opther words, two SpannedExpr instances
are equal if their ASTs are equal, even if their source spans are not.
Fields§
§origin: Origin<'src>The expression’s source origin.
inner: Expr<'src>The expression itself.
Implementations§
Source§impl<'a> SpannedExpr<'a>
impl<'a> SpannedExpr<'a>
Sourcepub fn contexts(&self) -> Vec<(&Context<'a>, &Origin<'a>)>
pub fn contexts(&self) -> Vec<(&Context<'a>, &Origin<'a>)>
Returns the contexts in this expression, along with their origins.
This includes all contexts in the expression, even those that don’t directly flow into
the evaluation. For example, ${{ foo.bar == 'abc' }} returns foo.bar since it’s a
context in the expression, even though it flows into a boolean evaluation rather than
directly into the output.
For dataflow contexts, see SpannedExpr::dataflow_contexts.
Sourcepub fn dataflow_contexts(&self) -> Vec<(&Context<'a>, &Origin<'a>)>
pub fn dataflow_contexts(&self) -> Vec<(&Context<'a>, &Origin<'a>)>
Returns the contexts in this expression that directly flow into the expression’s evaluation.
For example ${{ foo.bar }} returns foo.bar since the value
of foo.bar flows into the evaluation. On the other hand,
${{ foo.bar == 'abc' }} returns no expanded contexts,
since the value of foo.bar flows into a boolean evaluation
that gets expanded.
Sourcepub fn leaf_expressions(&self) -> Vec<&SpannedExpr<'a>>
pub fn leaf_expressions(&self) -> Vec<&SpannedExpr<'a>>
Returns all possible leaf expressions that could be the result of evaluating this expression.
Uses GitHub Actions’ short-circuit semantics:
A && B: only B can flow into the result (A is a condition)A || B: either A or B can be the result
Leaf expressions are any non-BinOp expressions: literals, contexts,
function calls, etc.
For example, ${{ foo.bar == 'true' && 'hello' || '' }} returns
['hello', ''] since those are the two possible evaluated values.
${{ foo.abc || foo.def }} returns [foo.abc, foo.def].
Sourcepub fn computed_indices(&self) -> Vec<&SpannedExpr<'a>>
pub fn computed_indices(&self) -> Vec<&SpannedExpr<'a>>
Returns any computed indices in this expression.
A computed index is any index operation with a non-literal
evaluation, e.g. foo[a.b.c].
Sourcepub fn constant_reducible_subexprs(&self) -> Vec<&SpannedExpr<'a>>
pub fn constant_reducible_subexprs(&self) -> Vec<&SpannedExpr<'a>>
Like Expr::constant_reducible, but for all subexpressions
rather than the top-level expression.
This has slightly different semantics than constant_reducible:
it doesn’t include “trivially” reducible expressions like literals,
since flagging these as reducible within a larger expression
would be misleading.
Methods from Deref<Target = Expr<'a>>§
Sourcepub fn is_literal(&self) -> bool
pub fn is_literal(&self) -> bool
Returns whether the expression is a literal.
Sourcepub fn constant_reducible(&self) -> bool
pub fn constant_reducible(&self) -> bool
Returns whether the expression is constant reducible.
“Constant reducible” is similar to “constant foldable” but with
meta-evaluation semantics: the expression 5 would not be
constant foldable in a normal program (because it’s already
an atom), but is “constant reducible” in a GitHub Actions expression
because an expression containing it (e.g. ${{ 5 }}) can be elided
entirely and replaced with 5.
There are three kinds of reducible expressions:
- Literals, which reduce to their literal value;
- Binops/unops with reducible subexpressions, which reduce to their evaluation;
- Select function calls where the semantics of the function mean that reducible arguments make the call itself reducible.
NOTE: This implementation is sound but not complete.
Sourcepub fn commutative_matches(&self, other: &Expr<'src>) -> bool
pub fn commutative_matches(&self, other: &Expr<'src>) -> bool
Returns whether this expression ‘commutatively matches’ the given expression.
For most expressions, this is the same as equivalence (i.e. ==).
For binary expressions that are also commutative, this takes commutivity into account.
For example, a == b is considered to match b == a, but a > b is not
considered to match b > a. This check is recusive, i.e. two nested binary expressions
will be fully checked for commutative equivalence.
Sourcepub fn consteval(&self) -> Option<Evaluation>
pub fn consteval(&self) -> Option<Evaluation>
Evaluates a constant-reducible expression to its literal value.
Returns Some(Evaluation) if the expression can be constant-evaluated,
or None if the expression contains non-constant elements (like contexts or
non-reducible function calls).
This implementation follows GitHub Actions’ evaluation semantics as documented at: https://docs.github.com/en/actions/reference/workflows-and-actions/expressions
§Examples
use github_actions_expressions::{Expr, Evaluation};
let expr = Expr::parse("'hello'").unwrap();
let result = expr.consteval().unwrap();
assert_eq!(result.sema().to_string(), "hello");
let expr = Expr::parse("true && false").unwrap();
let result = expr.consteval().unwrap();
assert_eq!(result, Evaluation::Boolean(false));