xee_ir/
ir.rs

1// an Intermediate Representation in ANF - administrative normal form
2// XXX is this really ANF? Maybe it is, though it doesn't support recursion
3// (without function arguments), as XPath doesn't.
4
5use ahash::{HashMap, HashMapExt};
6use ibig::IBig;
7use ordered_float::OrderedFloat;
8use rust_decimal::Decimal;
9
10pub use xee_interpreter::function::Name;
11use xee_interpreter::function::{CastType, Signature, StaticFunctionId};
12use xee_interpreter::xml;
13use xee_schema_type::Xs;
14pub use xee_xpath_ast::ast::{BinaryOperator, SequenceType, UnaryOperator};
15use xee_xpath_ast::span::Spanned;
16use xee_xpath_ast::Pattern;
17use xot::xmlname;
18
19pub type AtomS = Spanned<Atom>;
20pub type ExprS = Spanned<Expr>;
21
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum Expr {
24    Atom(AtomS),
25    Let(Let),
26    If(If),
27    Binary(Binary),
28    Unary(Unary),
29    FunctionDefinition(FunctionDefinition),
30    FunctionCall(FunctionCall),
31    Lookup(Lookup),
32    WildcardLookup(WildcardLookup),
33    Step(Step),
34    Deduplicate(Box<ExprS>),
35    Map(Map),
36    Filter(Filter),
37    PatternPredicate(PatternPredicate),
38    Quantified(Quantified),
39    Cast(Cast),
40    Castable(Castable),
41    InstanceOf(InstanceOf),
42    Treat(Treat),
43    MapConstructor(MapConstructor),
44    ArrayConstructor(ArrayConstructor),
45    XmlName(XmlName),
46    XmlDocument(XmlRoot),
47    XmlElement(XmlElement),
48    XmlAttribute(XmlAttribute),
49    XmlNamespace(XmlNamespace),
50    XmlText(XmlText),
51    XmlComment(XmlComment),
52    XmlProcessingInstruction(XmlProcessingInstruction),
53    XmlAppend(XmlAppend),
54    ApplyTemplates(ApplyTemplates),
55    CopyShallow(CopyShallow),
56    CopyDeep(CopyDeep),
57}
58
59// not to be confused with an XPath atom; this is a variable or a constant
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub enum Atom {
62    Const(Const),
63    Variable(Name),
64}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
67pub enum Const {
68    Integer(IBig),
69    String(String),
70    Double(OrderedFloat<f64>),
71    Decimal(Decimal),
72    StaticFunctionReference(StaticFunctionId, Option<ContextNames>),
73    // XXX replace this with a sequence constant? useful once we have constant folding
74    EmptySequence,
75}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct ContextNames {
79    pub item: Name,
80    pub position: Name,
81    pub last: Name,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
85pub struct Let {
86    pub name: Name,
87    pub var_expr: Box<ExprS>,
88    pub return_expr: Box<ExprS>,
89}
90
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub struct If {
93    pub condition: AtomS,
94    pub then: Box<ExprS>,
95    pub else_: Box<ExprS>,
96}
97
98#[derive(Debug, Clone, PartialEq, Eq)]
99pub struct Binary {
100    pub left: AtomS,
101    pub op: BinaryOperator,
102    pub right: AtomS,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct Unary {
107    pub op: UnaryOperator,
108    pub atom: AtomS,
109}
110
111#[derive(Debug, Clone, PartialEq, Eq)]
112pub struct FunctionDefinition {
113    pub params: Vec<Param>,
114    pub return_type: Option<SequenceType>,
115    pub body: Box<ExprS>,
116}
117
118impl FunctionDefinition {
119    pub fn signature(&self) -> Signature {
120        Signature::new(
121            self.params
122                .iter()
123                .map(|param| param.type_.clone())
124                .collect(),
125            self.return_type.clone(),
126        )
127    }
128}
129
130#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct Param {
132    pub name: Name,
133    pub type_: Option<SequenceType>,
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct FunctionCall {
138    pub atom: AtomS,
139    pub args: Vec<AtomS>,
140}
141
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct Lookup {
144    pub atom: AtomS,
145    pub arg_atom: AtomS,
146}
147
148#[derive(Debug, Clone, PartialEq, Eq)]
149pub struct WildcardLookup {
150    pub atom: AtomS,
151}
152
153#[derive(Debug, Clone, PartialEq, Eq)]
154pub struct Step {
155    pub step: xml::Step,
156    pub context: AtomS,
157}
158
159#[derive(Debug, Clone, PartialEq, Eq)]
160pub struct Map {
161    pub context_names: ContextNames,
162    pub var_atom: AtomS,
163    pub return_expr: Box<ExprS>,
164}
165
166#[derive(Debug, Clone, PartialEq, Eq)]
167pub struct Filter {
168    pub context_names: ContextNames,
169    pub var_atom: AtomS,
170    pub return_expr: Box<ExprS>,
171}
172
173#[derive(Debug, Clone, PartialEq, Eq)]
174pub struct PatternPredicate {
175    pub context_names: ContextNames,
176    pub var_atom: AtomS,
177    pub expr: Box<ExprS>,
178}
179
180#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct Quantified {
182    pub quantifier: Quantifier,
183    pub context_names: ContextNames,
184    pub var_atom: AtomS,
185    pub satisifies_expr: Box<ExprS>,
186}
187
188#[derive(Debug, Clone, PartialEq, Eq)]
189pub enum Quantifier {
190    Some,
191    Every,
192}
193
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct Cast {
196    pub atom: AtomS,
197    pub xs: Xs,
198    pub empty_sequence_allowed: bool,
199}
200
201impl Cast {
202    pub fn cast_type(&self) -> CastType {
203        CastType {
204            xs: self.xs,
205            empty_sequence_allowed: self.empty_sequence_allowed,
206        }
207    }
208}
209
210#[derive(Debug, Clone, PartialEq, Eq)]
211pub struct Castable {
212    pub atom: AtomS,
213    pub xs: Xs,
214    pub empty_sequence_allowed: bool,
215}
216
217impl Castable {
218    pub fn cast_type(&self) -> CastType {
219        CastType {
220            xs: self.xs,
221            empty_sequence_allowed: self.empty_sequence_allowed,
222        }
223    }
224}
225
226#[derive(Debug, Clone, PartialEq, Eq)]
227pub struct InstanceOf {
228    pub atom: AtomS,
229    pub sequence_type: SequenceType,
230}
231
232#[derive(Debug, Clone, PartialEq, Eq)]
233pub struct Treat {
234    pub atom: AtomS,
235    pub sequence_type: SequenceType,
236}
237
238#[derive(Debug, Clone, PartialEq, Eq)]
239pub struct MapConstructor {
240    pub members: Vec<(AtomS, AtomS)>,
241}
242
243#[derive(Debug, Clone, PartialEq, Eq)]
244pub enum ArrayConstructor {
245    Square(Vec<AtomS>),
246    Curly(AtomS),
247}
248
249// These are extensions to the IR that are only used by XSLT
250
251#[derive(Debug, Clone, PartialEq, Eq)]
252pub struct XmlName {
253    pub local_name: AtomS,
254    pub namespace: AtomS,
255}
256
257#[derive(Debug, Clone, PartialEq, Eq)]
258pub struct XmlRoot {}
259
260#[derive(Debug, Clone, PartialEq, Eq)]
261pub struct XmlElement {
262    pub name: AtomS,
263}
264
265#[derive(Debug, Clone, PartialEq, Eq)]
266pub struct XmlAttribute {
267    pub name: AtomS,
268    pub value: AtomS,
269}
270
271#[derive(Debug, Clone, PartialEq, Eq)]
272pub struct XmlNamespace {
273    pub prefix: AtomS,
274    pub namespace: AtomS,
275}
276
277#[derive(Debug, Clone, PartialEq, Eq)]
278pub struct XmlText {
279    pub value: AtomS,
280}
281
282#[derive(Debug, Clone, PartialEq, Eq)]
283pub struct XmlComment {
284    pub value: AtomS,
285}
286
287#[derive(Debug, Clone, PartialEq, Eq)]
288pub struct XmlProcessingInstruction {
289    pub target: AtomS,
290    pub content: AtomS,
291}
292
293#[derive(Debug, Clone, PartialEq, Eq)]
294pub struct XmlAppend {
295    pub parent: AtomS,
296    pub child: AtomS,
297}
298
299#[derive(Debug, Clone, PartialEq, Eq)]
300pub struct ApplyTemplates {
301    pub mode: ApplyTemplatesModeValue,
302    pub select: AtomS,
303}
304
305#[derive(Debug, Clone, PartialEq, Eq, Hash)]
306pub enum ApplyTemplatesModeValue {
307    Named(xmlname::OwnedName),
308    Unnamed,
309    Current,
310}
311
312#[derive(Debug, Clone, PartialEq, Eq)]
313pub struct CopyShallow {
314    pub select: AtomS,
315}
316
317#[derive(Debug, Clone, PartialEq, Eq)]
318pub struct CopyDeep {
319    pub select: AtomS,
320}
321
322#[derive(Debug, Clone, PartialEq, Eq)]
323pub struct Rule {
324    pub modes: Vec<ModeValue>,
325    pub priority: Decimal,
326    pub pattern: Pattern<FunctionDefinition>,
327    pub function_definition: FunctionDefinition,
328}
329
330#[derive(Debug, Clone, PartialEq, Eq, Hash)]
331pub enum ModeValue {
332    Named(xmlname::OwnedName),
333    Unnamed,
334    All,
335}
336
337#[derive(Debug, Clone, PartialEq, Eq)]
338pub struct Mode {}
339
340#[derive(Debug, Clone, PartialEq, Eq)]
341pub struct Declarations {
342    pub rules: Vec<Rule>,
343    pub modes: HashMap<Option<xmlname::OwnedName>, Mode>,
344    pub functions: Vec<FunctionBinding>,
345    pub main: FunctionDefinition,
346}
347
348impl Declarations {
349    pub fn new(main: FunctionDefinition) -> Self {
350        Self {
351            rules: Vec::new(),
352            modes: HashMap::new(),
353            functions: Vec::new(),
354            main,
355        }
356    }
357}
358
359#[derive(Debug, Clone, PartialEq, Eq)]
360pub struct FunctionBinding {
361    pub name: Name,
362    pub main: FunctionDefinition,
363}