Skip to main content

bel/common/ast/
mod.rs

1use std::collections::BTreeMap;
2
3use crate::common::value::CelVal;
4
5pub mod operators;
6
7pub struct Ast {
8    pub expr: IdedExpr,
9}
10
11#[derive(Clone, Debug, Default, PartialEq)]
12pub enum Expr {
13    #[default]
14    /// UnspecifiedExprKind represents an unset expression with no specified properties.
15    Unspecified,
16
17    /// CallKind represents a function call.
18    Call(CallExpr),
19
20    /// ComprehensionKind represents a comprehension expression generated by a macro.
21    Comprehension(Box<ComprehensionExpr>),
22
23    /// IdentKind represents a simple variable, constant, or type identifier.
24    Ident(String),
25
26    /// ListKind represents a list literal expression.
27    List(ListExpr),
28
29    /// LiteralKind represents a primitive scalar literal.
30    Literal(CelVal),
31
32    /// MapKind represents a map literal expression.
33    Map(MapExpr),
34
35    /// SelectKind represents a field selection expression.
36    Select(SelectExpr),
37
38    /// StructKind represents a struct literal expression.
39    Struct(StructExpr),
40}
41
42#[derive(Clone, Debug, PartialEq)]
43pub enum EntryExpr {
44    StructField(StructFieldExpr),
45    MapEntry(MapEntryExpr),
46}
47
48#[derive(Clone, Debug, Default, PartialEq)]
49pub struct IdedExpr {
50    pub id: u64,
51    pub expr: Expr,
52}
53
54#[derive(Clone, Debug, PartialEq)]
55pub struct IdedEntryExpr {
56    pub id: u64,
57    pub expr: EntryExpr,
58}
59
60#[derive(Clone, Debug, Default, PartialEq)]
61pub struct CallExpr {
62    pub func_name: String,
63    pub target: Option<Box<IdedExpr>>,
64    pub args: Vec<IdedExpr>,
65}
66
67#[derive(Clone, Debug, Default, PartialEq)]
68pub struct SelectExpr {
69    pub operand: Box<IdedExpr>,
70    pub field: String,
71    pub test: bool,
72}
73
74#[derive(Clone, Debug, Default, PartialEq)]
75pub struct StructExpr {
76    pub type_name: String,
77    pub entries: Vec<IdedEntryExpr>,
78}
79
80#[derive(Clone, Debug, Default, PartialEq)]
81pub struct MapExpr {
82    pub entries: Vec<IdedEntryExpr>,
83}
84
85#[derive(Clone, Debug, Default, PartialEq)]
86pub struct ListExpr {
87    pub elements: Vec<IdedExpr>,
88}
89
90#[derive(Clone, Debug, Default, PartialEq)]
91pub struct StructFieldExpr {
92    pub field: String,
93    pub value: IdedExpr,
94    pub optional: bool,
95}
96
97#[derive(Clone, Debug, Default, PartialEq)]
98pub struct MapEntryExpr {
99    pub key: IdedExpr,
100    pub value: IdedExpr,
101    pub optional: bool,
102}
103
104#[derive(Clone, Debug, Default, PartialEq)]
105pub struct ComprehensionExpr {
106    pub iter_range: IdedExpr,
107    pub iter_var: String,
108    pub iter_var2: Option<String>,
109    pub accu_var: String,
110    pub accu_init: IdedExpr,
111    pub loop_cond: IdedExpr,
112    pub loop_step: IdedExpr,
113    pub result: IdedExpr,
114}
115
116#[derive(Debug, Default)]
117pub struct SourceInfo {
118    offsets: BTreeMap<u64, OffsetRange>,
119    pub source: String,
120}
121
122impl SourceInfo {
123    pub fn add_offset(&mut self, id: u64, start: u32, stop: u32) {
124        self.offsets.insert(
125            id,
126            OffsetRange {
127                start,
128                stop,
129            },
130        );
131    }
132
133    pub fn offset_for(&self, id: u64) -> Option<(u32, u32)> {
134        self.offsets.get(&id).map(|range| (range.start, range.stop))
135    }
136
137    pub(crate) fn pos_for(&self, id: u64) -> Option<(isize, isize)> {
138        match self.offset_for(id) {
139            Some((start, _)) => {
140                let start = start as isize;
141                let mut offset = 0;
142                let mut line = 0;
143                for l in self.source.split_inclusive('\n') {
144                    line += 1;
145                    offset += l.len() as isize;
146                    if start < offset {
147                        return Some((line, start + (l.len() as isize) - offset + 1));
148                    }
149                }
150                None
151            }
152            None => None,
153        }
154    }
155
156    pub fn snippet(&self, line: isize) -> Option<&str> {
157        self.source.lines().nth(line as usize)
158    }
159}
160
161#[derive(Clone, Debug, Default, PartialEq)]
162pub struct OffsetRange {
163    pub start: u32,
164    pub stop: u32,
165}