qraft_core/expression/
in.rs1use crate::{
4 LowerCompatible, NullOf, PredicateType, TypeMeta, UnaryType, count_idents,
5 expression::Expression,
6 impl_for_all_tuples,
7 lower::{Instructions, LowerCtx},
8 ty::Nullability,
9};
10
11pub struct InList<L, R> {
13 lhs: L,
14 rhs: R,
15 negated: bool,
16}
17
18#[qraft_expression_macro::as_expression]
19impl<L, R> Expression for InList<L, R>
20where
21 L: Expression,
22 L::Type: Nullability,
23 R: LowerIn<L::Type>,
24 UnaryType<NullOf<L::Type>>: PredicateType,
25{
26 type Type = <UnaryType<NullOf<L::Type>> as PredicateType>::Output;
27
28 fn lower(&self, ctx: &mut LowerCtx) -> usize {
29 let lhs = self.lhs.lower(ctx);
30 let rhs = self.rhs.lower_in(ctx);
31 ctx.lower_in(self.negated, lhs, rhs)
32 }
33}
34
35pub trait In: Sized + Expression {
37 fn one_of<R>(self, list: R) -> InList<Self, R>
38 where
39 R: LowerIn<Self::Type>,
40 {
41 self.in_(list)
42 }
43
44 fn in_<R>(self, list: R) -> InList<Self, R>
45 where
46 R: LowerIn<Self::Type>,
47 {
48 InList {
49 lhs: self,
50 rhs: list,
51 negated: false,
52 }
53 }
54
55 fn not_in<R>(self, list: R) -> InList<Self, R>
56 where
57 R: LowerIn<Self::Type>,
58 {
59 InList {
60 lhs: self,
61 rhs: list,
62 negated: true,
63 }
64 }
65}
66
67impl<E> In for E where E: Expression {}
68
69pub trait LowerIn<T> {
71 fn lower_in(&self, ctx: &mut LowerCtx) -> usize;
73}
74
75impl<Type, A> LowerIn<Type> for (A,)
76where
77 Type: TypeMeta,
78 A: LowerCompatible<Type>,
79{
80 fn lower_in(&self, ctx: &mut LowerCtx) -> usize {
81 let (a,) = self;
82 let inner = a.lower_compatible(ctx);
83 ctx.instrs.push_seperated(1);
84 inner + 1
85 }
86}
87
88impl<Type, A> LowerIn<Type> for Vec<A>
89where
90 Type: TypeMeta,
91 A: LowerCompatible<Type>,
92{
93 fn lower_in(&self, ctx: &mut LowerCtx) -> usize {
94 let len = self.len();
95 let mut inner = 0;
96 for item in self {
97 inner += item.lower_compatible(ctx);
98 }
99 ctx.instrs.push_seperated(len);
100 inner + 1
101 }
102}
103
104impl<Type, A, const N: usize> LowerIn<Type> for [A; N]
105where
106 Type: TypeMeta,
107 A: LowerCompatible<Type>,
108{
109 fn lower_in(&self, ctx: &mut LowerCtx) -> usize {
110 let len = self.len();
111 let mut inner = 0;
112 for item in self {
113 inner += item.lower_compatible(ctx);
114 }
115 ctx.instrs.push_seperated(len);
116 inner + 1
117 }
118}
119
120macro_rules! impl_in_macro {
121 ($($T:ident),+) => {
122 impl<Type, $($T,)+> LowerIn<Type> for ($($T,)+)
123 where
124 Type: TypeMeta,
125 $($T: LowerCompatible<Type>,)+
126 {
127 fn lower_in(&self, ctx: &mut LowerCtx) -> usize {
128 let mut inner = 0;
129 #[allow(non_snake_case)]
130 let ($($T,)+) = self;
131 $(
132 inner += $T.lower_compatible(ctx);
133 )+
134 let count = count_idents!($($T,)+);
135 ctx.instrs.push_seperated(count);
136 inner + 1
137 }
138 }
139 };
140}
141
142impl_for_all_tuples!(impl_in_macro);