ISLE: add support for multi-extractors and multi-constructors. (#4908)
* ISLE: add support for multi-extractors and multi-constructors. This support allows for rules that process multiple matching values per extractor call on the left-hand side, and as a result, can produce multiple values from the constructor whose body they define. This is useful in situations where we are matching on an input data structure that can have multiple "nodes" for a given value or ID, for example in an e-graph. * Review feedback: all multi-ctors and multi-etors return iterators; no `Vec` case. * Add additional warning suppressions to generated-code toplevels to be consistent with new islec output.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
(type u32 (primitive u32))
|
||||
|
||||
(decl multi A (u32) u32)
|
||||
(extractor (A x) x)
|
||||
@@ -0,0 +1,15 @@
|
||||
(type u32 (primitive u32))
|
||||
|
||||
(decl multi A (u32) u32)
|
||||
(decl multi B (u32) u32)
|
||||
(decl multi C (u32) u32)
|
||||
(decl multi D (u32) u32)
|
||||
|
||||
(extern constructor B ctor_B)
|
||||
(extern extractor C etor_C)
|
||||
|
||||
(rule (A x)
|
||||
(B x))
|
||||
|
||||
(rule (D (C x))
|
||||
(B x))
|
||||
@@ -0,0 +1,57 @@
|
||||
mod multi_constructor;
|
||||
|
||||
pub(crate) type ConstructorVec<T> = Vec<T>;
|
||||
|
||||
struct Context;
|
||||
|
||||
struct It {
|
||||
i: u32,
|
||||
limit: u32,
|
||||
}
|
||||
|
||||
impl multi_constructor::ContextIter for It {
|
||||
type Context = Context;
|
||||
type Output = u32;
|
||||
fn next(&mut self, _ctx: &mut Self::Context) -> Option<u32> {
|
||||
if self.i >= self.limit {
|
||||
None
|
||||
} else {
|
||||
let i = self.i;
|
||||
self.i += 1;
|
||||
Some(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl multi_constructor::Context for Context {
|
||||
type etor_C_iter = It;
|
||||
fn etor_C(&mut self, value: u32) -> Option<It> {
|
||||
Some(It { i: 0, limit: value })
|
||||
}
|
||||
|
||||
type ctor_B_iter = multi_constructor::ContextIterWrapper<u32, std::vec::IntoIter<u32>, Context>;
|
||||
fn ctor_B(&mut self, value: u32) -> Option<Self::ctor_B_iter> {
|
||||
Some((0..value).rev().collect::<Vec<_>>().into_iter().into())
|
||||
}
|
||||
}
|
||||
|
||||
struct IterWithContext<'a, Item, I: multi_constructor::ContextIter<Output = Item, Context = Context>> {
|
||||
ctx: &'a mut Context,
|
||||
it: I,
|
||||
}
|
||||
|
||||
impl<'a, Item, I: multi_constructor::ContextIter<Output = Item, Context = Context>> Iterator for IterWithContext<'a, Item, I> {
|
||||
type Item = Item;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.it.next(self.ctx)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut ctx = Context;
|
||||
let l1 = multi_constructor::constructor_A(&mut ctx, 10).unwrap();
|
||||
let l2 = multi_constructor::constructor_D(&mut ctx, 5).unwrap();
|
||||
let l1 = IterWithContext { ctx: &mut ctx, it: l1 }.collect::<Vec<_>>();
|
||||
let l2 = IterWithContext { ctx: &mut ctx, it: l2 }.collect::<Vec<_>>();
|
||||
println!("l1 = {:?} l2 = {:?}", l1, l2);
|
||||
}
|
||||
14
cranelift/isle/isle/isle_examples/link/multi_extractor.isle
Normal file
14
cranelift/isle/isle/isle_examples/link/multi_extractor.isle
Normal file
@@ -0,0 +1,14 @@
|
||||
(type u32 (primitive u32))
|
||||
(type A extern (enum (B) (C)))
|
||||
|
||||
(decl multi E1 (A u32) u32)
|
||||
|
||||
(extern extractor E1 e1_etor)
|
||||
|
||||
(decl Rule (u32) u32)
|
||||
|
||||
(rule (Rule (E1 a idx))
|
||||
(if-let (A.B) a)
|
||||
idx)
|
||||
(rule (Rule _)
|
||||
32)
|
||||
@@ -0,0 +1,46 @@
|
||||
mod multi_extractor;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum A {
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
struct It {
|
||||
i: u32,
|
||||
arg: u32,
|
||||
}
|
||||
|
||||
impl multi_extractor::ContextIter for It {
|
||||
type Context = Context;
|
||||
type Output = (A, u32);
|
||||
fn next(&mut self, _ctx: &mut Self::Context) -> Option<Self::Output> {
|
||||
if self.i >= 32 {
|
||||
None
|
||||
} else {
|
||||
let idx = self.i;
|
||||
self.i += 1;
|
||||
let a = if self.arg & (1u32 << idx) != 0 {
|
||||
A::B
|
||||
} else {
|
||||
A::C
|
||||
};
|
||||
Some((a, idx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Context;
|
||||
impl multi_extractor::Context for Context {
|
||||
type e1_etor_iter = It;
|
||||
fn e1_etor(&mut self, arg0: u32) -> Option<It> {
|
||||
Some(It { i: 0, arg: arg0 })
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut ctx = Context;
|
||||
let x = multi_extractor::constructor_Rule(&mut ctx, 0xf0);
|
||||
let y = multi_extractor::constructor_Rule(&mut ctx, 0);
|
||||
println!("x = {:?} y = {:?}", x, y);
|
||||
}
|
||||
Reference in New Issue
Block a user