Add match blocks capable of matching against enum variants
This commit is contained in:
parent
062bd8abd7
commit
2918260c5a
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -783,6 +783,7 @@ dependencies = [
|
|||||||
"itertools",
|
"itertools",
|
||||||
"pollster",
|
"pollster",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ pub enum Block {
|
|||||||
ComponentElement(ComponentElement),
|
ComponentElement(ComponentElement),
|
||||||
IfBlock(IfBlock),
|
IfBlock(IfBlock),
|
||||||
ForBlock(ForBlock),
|
ForBlock(ForBlock),
|
||||||
|
MatchBlock(MatchBlock),
|
||||||
Text(StringExpr),
|
Text(StringExpr),
|
||||||
DefineExpandSlot(DefineExpandSlot),
|
DefineExpandSlot(DefineExpandSlot),
|
||||||
DefineFragment(DefineFragment),
|
DefineFragment(DefineFragment),
|
||||||
@ -53,6 +54,25 @@ pub struct ForBlock {
|
|||||||
pub loc: Locator,
|
pub loc: Locator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||||
|
pub struct MatchBlock {
|
||||||
|
pub matchable: Expression,
|
||||||
|
pub arms: Vec<(MatchBinding, Vec<Block>)>,
|
||||||
|
pub loc: Locator,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||||
|
pub enum MatchBinding {
|
||||||
|
/// `Some(x) =>`
|
||||||
|
TupleVariant { name: IStr, pieces: Vec<Binding> },
|
||||||
|
|
||||||
|
/// `None =>`
|
||||||
|
UnitVariant { name: IStr },
|
||||||
|
|
||||||
|
/// `_ =>`
|
||||||
|
Ignore,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||||
pub enum Binding {
|
pub enum Binding {
|
||||||
Variable(IStr),
|
Variable(IStr),
|
||||||
|
@ -12,6 +12,7 @@ BlockContent = _{
|
|||||||
Text |
|
Text |
|
||||||
DefineExpandSlot |
|
DefineExpandSlot |
|
||||||
ForBlock |
|
ForBlock |
|
||||||
|
MatchBlock |
|
||||||
DefineFragment
|
DefineFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,6 +56,25 @@ EmptyForBlock = {
|
|||||||
PEEK_ALL ~ "empty" ~ lineEnd ~ NewBlock
|
PEEK_ALL ~ "empty" ~ lineEnd ~ NewBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MatchBlock = {
|
||||||
|
"match" ~ ws+ ~ Expr ~ lineEnd ~
|
||||||
|
PEEK_ALL ~ PUSH(" "+ | "\t"+) ~ MatchArm ~
|
||||||
|
(PEEK_ALL ~ MatchArm)* ~ DROP
|
||||||
|
}
|
||||||
|
MatchArm = {
|
||||||
|
MatchBinding ~ ws* ~ "=>" ~ lineEnd ~ NewBlock
|
||||||
|
}
|
||||||
|
MatchBinding = {
|
||||||
|
MBTupleVariant | IgnoreBinding | MBUnitVariant
|
||||||
|
}
|
||||||
|
|
||||||
|
MBTupleVariant = {
|
||||||
|
Identifier ~ ws* ~ "(" ~ ws* ~ (Binding ~ ws* ~ ("," ~ ws* ~ Binding ~ ws*)*)? ~ ")"
|
||||||
|
}
|
||||||
|
MBUnitVariant = {
|
||||||
|
Identifier
|
||||||
|
}
|
||||||
|
|
||||||
DefineExpandSlot = {
|
DefineExpandSlot = {
|
||||||
SlotOptional? ~ "slot" ~ ws+ ~ ":" ~ Identifier ~ lineEnd
|
SlotOptional? ~ "slot" ~ ws+ ~ ":" ~ Identifier ~ lineEnd
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
Binding, Block, ComponentElement, DefineExpandSlot, DefineFragment, Expression, ForBlock,
|
Binding, Block, ComponentElement, DefineExpandSlot, DefineFragment, Expression, ForBlock,
|
||||||
HtmlElement, IfBlock, StringExpr, StringPiece, Template,
|
HtmlElement, IfBlock, MatchBinding, MatchBlock, StringExpr, StringPiece, Template,
|
||||||
};
|
};
|
||||||
use crate::{intern, IStr, Locator};
|
use crate::{intern, IStr, Locator};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@ -374,6 +374,50 @@ impl HornbeamParser {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn MatchBlock(input: Node) -> PCResult<Block> {
|
||||||
|
let loc = nodeloc(&input);
|
||||||
|
|
||||||
|
let (expr, arms) = match_nodes!(input.into_children();
|
||||||
|
[Expr(expr), MatchArm(arms)..] => (expr, arms.collect())
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(Block::MatchBlock(MatchBlock {
|
||||||
|
matchable: expr,
|
||||||
|
arms,
|
||||||
|
loc,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn MatchArm(input: Node) -> PCResult<(MatchBinding, Vec<Block>)> {
|
||||||
|
Ok(match_nodes!(input.into_children();
|
||||||
|
[MatchBinding(binding), blocks..] => (
|
||||||
|
binding,
|
||||||
|
HornbeamParser::helper_blocks(blocks)?,
|
||||||
|
)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn MatchBinding(input: Node) -> PCResult<MatchBinding> {
|
||||||
|
Ok(match_nodes!(input.into_children();
|
||||||
|
[MBTupleVariant(mb)] => mb,
|
||||||
|
[MBUnitVariant(mb)] => mb,
|
||||||
|
[IgnoreBinding(_)] => MatchBinding::Ignore,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn MBTupleVariant(input: Node) -> PCResult<MatchBinding> {
|
||||||
|
Ok(match_nodes!(input.into_children();
|
||||||
|
[Identifier(name), Binding(bindings)..] => {
|
||||||
|
MatchBinding::TupleVariant { name, pieces: bindings.collect() }
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn MBUnitVariant(input: Node) -> PCResult<MatchBinding> {
|
||||||
|
let name = Self::Identifier(input.into_children().single()?)?;
|
||||||
|
Ok(MatchBinding::UnitVariant { name })
|
||||||
|
}
|
||||||
|
|
||||||
fn Binding(input: Node) -> PCResult<Binding> {
|
fn Binding(input: Node) -> PCResult<Binding> {
|
||||||
Ok(match_nodes!(input.into_children();
|
Ok(match_nodes!(input.into_children();
|
||||||
[VarBinding(b)] => b,
|
[VarBinding(b)] => b,
|
||||||
@ -421,6 +465,7 @@ impl HornbeamParser {
|
|||||||
Rule::Text => Some(HornbeamParser::Text(input)?),
|
Rule::Text => Some(HornbeamParser::Text(input)?),
|
||||||
Rule::IfBlock => Some(HornbeamParser::IfBlock(input)?),
|
Rule::IfBlock => Some(HornbeamParser::IfBlock(input)?),
|
||||||
Rule::ForBlock => Some(HornbeamParser::ForBlock(input)?),
|
Rule::ForBlock => Some(HornbeamParser::ForBlock(input)?),
|
||||||
|
Rule::MatchBlock => Some(HornbeamParser::MatchBlock(input)?),
|
||||||
Rule::DefineFragment => Some(HornbeamParser::DefineFragment(input)?),
|
Rule::DefineFragment => Some(HornbeamParser::DefineFragment(input)?),
|
||||||
Rule::DefineExpandSlot => Some(HornbeamParser::DefineExpandSlot(input)?),
|
Rule::DefineExpandSlot => Some(HornbeamParser::DefineExpandSlot(input)?),
|
||||||
Rule::EOI => None,
|
Rule::EOI => None,
|
||||||
@ -540,6 +585,22 @@ empty
|
|||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_blocks() {
|
||||||
|
assert_yaml_snapshot!(parse_template(
|
||||||
|
r#"
|
||||||
|
if $x
|
||||||
|
match $y
|
||||||
|
None =>
|
||||||
|
"None"
|
||||||
|
Some($z) =>
|
||||||
|
"Some(${$z})"
|
||||||
|
"#,
|
||||||
|
"inp"
|
||||||
|
)
|
||||||
|
.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fragments_and_slots() {
|
fn fragments_and_slots() {
|
||||||
assert_yaml_snapshot!(parse_template(
|
assert_yaml_snapshot!(parse_template(
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
source: hornbeam_grammar/src/parser.rs
|
||||||
|
expression: "parse_template(r#\"\nif $x\n match $y\n None =>\n \"None\"\n Some($z) =>\n \"Some(${$z})\"\n \"#,\n \"inp\").unwrap()"
|
||||||
|
---
|
||||||
|
blocks:
|
||||||
|
- IfBlock:
|
||||||
|
condition:
|
||||||
|
Variable:
|
||||||
|
name: x
|
||||||
|
loc:
|
||||||
|
filename: inp
|
||||||
|
line: 2
|
||||||
|
column: 4
|
||||||
|
blocks:
|
||||||
|
- MatchBlock:
|
||||||
|
matchable:
|
||||||
|
Variable:
|
||||||
|
name: y
|
||||||
|
loc:
|
||||||
|
filename: inp
|
||||||
|
line: 3
|
||||||
|
column: 11
|
||||||
|
arms:
|
||||||
|
- - UnitVariant:
|
||||||
|
name: None
|
||||||
|
- - Text:
|
||||||
|
pieces:
|
||||||
|
- Literal: None
|
||||||
|
- - TupleVariant:
|
||||||
|
name: Some
|
||||||
|
pieces:
|
||||||
|
- Variable: z
|
||||||
|
- - Text:
|
||||||
|
pieces:
|
||||||
|
- Literal: Some(
|
||||||
|
- Interpolation:
|
||||||
|
Variable:
|
||||||
|
name: z
|
||||||
|
loc:
|
||||||
|
filename: inp
|
||||||
|
line: 7
|
||||||
|
column: 21
|
||||||
|
- Literal: )
|
||||||
|
loc:
|
||||||
|
filename: inp
|
||||||
|
line: 3
|
||||||
|
column: 5
|
||||||
|
else_blocks: []
|
||||||
|
loc:
|
||||||
|
filename: inp
|
||||||
|
line: 2
|
||||||
|
column: 1
|
||||||
|
|
@ -22,6 +22,8 @@ itertools = "0.10.5"
|
|||||||
|
|
||||||
pollster = "0.3.0"
|
pollster = "0.3.0"
|
||||||
|
|
||||||
|
tracing = "0.1.37"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["fluent"]
|
default = ["fluent"]
|
||||||
fluent = ["fluent-templates"]
|
fluent = ["fluent-templates"]
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::interface::{LocalisationSystem, OutputSystem};
|
use crate::interface::{LocalisationSystem, OutputSystem};
|
||||||
use crate::InterpreterError;
|
use crate::InterpreterError;
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use bevy_reflect::{FromReflect, Reflect, ReflectRef};
|
use bevy_reflect::{FromReflect, Reflect, ReflectRef, VariantType};
|
||||||
use fluent_templates::lazy_static::lazy_static;
|
use fluent_templates::lazy_static::lazy_static;
|
||||||
use hornbeam_grammar::ast::Binding;
|
use hornbeam_grammar::ast::{Binding, MatchBinding};
|
||||||
use hornbeam_grammar::Locator;
|
use hornbeam_grammar::Locator;
|
||||||
use hornbeam_ir::ir::{Expression, Step, StepDef, StringPiece};
|
use hornbeam_ir::ir::{Expression, Step, StepDef, StringPiece};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@ -13,6 +13,7 @@ use std::collections::BTreeMap;
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use tracing::warn;
|
||||||
|
|
||||||
pub(crate) struct FilledSlot<'a> {
|
pub(crate) struct FilledSlot<'a> {
|
||||||
pub scope_idx: usize,
|
pub scope_idx: usize,
|
||||||
@ -249,7 +250,7 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => {
|
_ => {
|
||||||
return Err(InterpreterError::TypeError {
|
return Err(InterpreterError::TypeError {
|
||||||
context: "For".to_string(),
|
context: "For".to_string(),
|
||||||
conflict: format!("not iterable reflective: {reflective:?}."),
|
conflict: format!("not iterable reflective: {reflective:?}."),
|
||||||
@ -268,6 +269,131 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
StepDef::Match { matchable, arms } => {
|
||||||
|
let matchable_evaled =
|
||||||
|
self.evaluate_expression(scope_idx, matchable, &step.locator)?;
|
||||||
|
|
||||||
|
for (arm_binding, arm_steps) in arms {
|
||||||
|
// if this arm's binding matches, then bind the variable...
|
||||||
|
match arm_binding {
|
||||||
|
MatchBinding::UnitVariant { name } => {
|
||||||
|
match &matchable_evaled {
|
||||||
|
Value::Reflective(reflective) => match reflective.reflect_ref() {
|
||||||
|
ReflectRef::Enum(reflenum) => {
|
||||||
|
// Check if the variant name matches!
|
||||||
|
if reflenum.variant_name() != name as &str {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!("trying to `match` weird reflective: {reflective:?} vs {name} at {}", step.locator);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
warn!(
|
||||||
|
"trying to `match` non-reflective vs {name} at {}",
|
||||||
|
step.locator
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MatchBinding::TupleVariant { name, pieces } => {
|
||||||
|
match &matchable_evaled {
|
||||||
|
Value::Reflective(reflective) => match reflective.reflect_ref() {
|
||||||
|
ReflectRef::Enum(reflenum) => {
|
||||||
|
// Check if the variant name matches!
|
||||||
|
if reflenum.variant_name() != name as &str {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind the pieces!
|
||||||
|
if pieces.len() != reflenum.field_len() {
|
||||||
|
return Err(InterpreterError::TypeError {
|
||||||
|
context: "Match".to_string(),
|
||||||
|
conflict: format!("wrong number of tuple pieces on {name}: wanted {}, found {}", pieces.len(), reflenum.field_len()),
|
||||||
|
location: step.locator.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if reflenum.variant_type() != VariantType::Tuple {
|
||||||
|
return Err(InterpreterError::TypeError {
|
||||||
|
context: "Match".to_string(),
|
||||||
|
conflict: format!(
|
||||||
|
"not a tuple variant: {name} is a {:?}",
|
||||||
|
reflenum.variant_type()
|
||||||
|
),
|
||||||
|
location: step.locator.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (piece, field) in
|
||||||
|
pieces.iter().zip(reflenum.iter_fields())
|
||||||
|
{
|
||||||
|
// TODO duplicated code. Should probably make some 'Binder' tool that also makes it easy to unbind afterwards!
|
||||||
|
match piece {
|
||||||
|
Binding::Variable(var) => {
|
||||||
|
self.scopes[scope_idx].variables.insert(
|
||||||
|
String::from(var as &str),
|
||||||
|
// TODO would be nice to avoid this clone!
|
||||||
|
Value::from_reflect(
|
||||||
|
field.value().clone_value(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Binding::Ignore => {
|
||||||
|
// nop.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!("trying to `match` weird reflective: {reflective:?} vs {name}(...) at {}", step.locator);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
warn!(
|
||||||
|
"trying to `match` non-reflective vs {name}(...) at {}",
|
||||||
|
step.locator
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MatchBinding::Ignore => {
|
||||||
|
// always matches: no variable to bind, no conditions to check!
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// and then execute the instructions
|
||||||
|
self.run_steps(scope_idx, arm_steps).await?;
|
||||||
|
|
||||||
|
// and then unbind the variables.
|
||||||
|
match arm_binding {
|
||||||
|
MatchBinding::TupleVariant { pieces, .. } => {
|
||||||
|
for piece in pieces {
|
||||||
|
// TODO duplicated code. Should probably make some 'Binder' tool that also makes it easy to unbind afterwards!
|
||||||
|
match piece {
|
||||||
|
Binding::Variable(var) => {
|
||||||
|
self.scopes[scope_idx].variables.remove(var as &str);
|
||||||
|
}
|
||||||
|
Binding::Ignore => {
|
||||||
|
// nop.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MatchBinding::UnitVariant { .. } | MatchBinding::Ignore => {
|
||||||
|
// no variables to unbind
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// (don't fall through to other arms since we matched this one)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
StepDef::Call { name, args, slots } => {
|
StepDef::Call { name, args, slots } => {
|
||||||
let mut evaled_args = BTreeMap::new();
|
let mut evaled_args = BTreeMap::new();
|
||||||
for (key, expr) in args {
|
for (key, expr) in args {
|
||||||
|
@ -96,6 +96,13 @@ fn pull_out_entrypoints_from_block<'a>(
|
|||||||
pull_out_entrypoints_from_block(child, template_name, target)?;
|
pull_out_entrypoints_from_block(child, template_name, target)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Block::MatchBlock(matchb) => {
|
||||||
|
for (_arm_binding, arm_blocks) in &mut matchb.arms {
|
||||||
|
for child in arm_blocks {
|
||||||
|
pull_out_entrypoints_from_block(child, template_name, target)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Block::DefineFragment(frag) => {
|
Block::DefineFragment(frag) => {
|
||||||
// First process children
|
// First process children
|
||||||
for child in &mut frag.blocks {
|
for child in &mut frag.blocks {
|
||||||
@ -349,6 +356,26 @@ fn compile_ast_block_to_steps<'a>(
|
|||||||
locator: forb.loc.clone(),
|
locator: forb.loc.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Block::MatchBlock(matchb) => {
|
||||||
|
let mut arms_instrs = Vec::new();
|
||||||
|
|
||||||
|
for (arm_binding, arm_blocks) in &matchb.arms {
|
||||||
|
let mut this_arm_instrs = Vec::new();
|
||||||
|
for b in arm_blocks {
|
||||||
|
compile_ast_block_to_steps(b, &mut this_arm_instrs)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
arms_instrs.push((arm_binding.clone(), this_arm_instrs));
|
||||||
|
}
|
||||||
|
|
||||||
|
instructions.push(Step {
|
||||||
|
def: StepDef::Match {
|
||||||
|
matchable: matchb.matchable.clone(),
|
||||||
|
arms: arms_instrs,
|
||||||
|
},
|
||||||
|
locator: matchb.loc.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
Block::Text(text) => {
|
Block::Text(text) => {
|
||||||
for piece in &text.pieces {
|
for piece in &text.pieces {
|
||||||
match piece {
|
match piece {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use hornbeam_grammar::ast::Binding;
|
use hornbeam_grammar::ast::{Binding, MatchBinding};
|
||||||
pub use hornbeam_grammar::ast::{Expression, StringPiece};
|
pub use hornbeam_grammar::ast::{Expression, StringPiece};
|
||||||
use hornbeam_grammar::{IStr, Locator};
|
use hornbeam_grammar::{IStr, Locator};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -39,6 +39,10 @@ pub enum StepDef {
|
|||||||
body_steps: Vec<Step>,
|
body_steps: Vec<Step>,
|
||||||
empty_steps: Vec<Step>,
|
empty_steps: Vec<Step>,
|
||||||
},
|
},
|
||||||
|
Match {
|
||||||
|
matchable: Expression,
|
||||||
|
arms: Vec<(MatchBinding, Vec<Step>)>,
|
||||||
|
},
|
||||||
Call {
|
Call {
|
||||||
name: IStr,
|
name: IStr,
|
||||||
args: BTreeMap<IStr, Expression>,
|
args: BTreeMap<IStr, Expression>,
|
||||||
|
@ -70,6 +70,11 @@ fn apply_peephole_pass<F: Fn(&mut Vec<Step>)>(steps: &mut Vec<Step>, pass: &F) {
|
|||||||
apply_peephole_pass(body_steps, pass);
|
apply_peephole_pass(body_steps, pass);
|
||||||
apply_peephole_pass(empty_steps, pass);
|
apply_peephole_pass(empty_steps, pass);
|
||||||
}
|
}
|
||||||
|
StepDef::Match { arms, .. } => {
|
||||||
|
for (_, arm_steps) in arms {
|
||||||
|
apply_peephole_pass(arm_steps, pass);
|
||||||
|
}
|
||||||
|
}
|
||||||
StepDef::Call { slots, .. } => {
|
StepDef::Call { slots, .. } => {
|
||||||
for slot_steps in slots.values_mut() {
|
for slot_steps in slots.values_mut() {
|
||||||
apply_peephole_pass(slot_steps, pass);
|
apply_peephole_pass(slot_steps, pass);
|
||||||
|
Loading…
Reference in New Issue
Block a user