use crate::reference::Val;
use std::collections::BTreeMap;
pub mod operators;
pub struct Ast {
pub expr: IdedExpr,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub enum Expr {
#[default]
Unspecified,
Call(CallExpr),
Comprehension(ComprehensionExpr),
Ident(String),
List(ListExpr),
Literal(Val),
Map(MapExpr),
Select(SelectExpr),
Struct(StructExpr),
}
#[derive(Clone, Debug, PartialEq)]
pub enum EntryExpr {
StructField(StructFieldExpr),
MapEntry(MapEntryExpr),
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct IdedExpr {
pub id: u64,
pub expr: Expr,
}
#[derive(Clone, Debug, PartialEq)]
pub struct IdedEntryExpr {
pub id: u64,
pub expr: EntryExpr,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct CallExpr {
pub func_name: String,
pub target: Option<Box<IdedExpr>>,
pub args: Vec<IdedExpr>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct SelectExpr {
pub operand: Box<IdedExpr>,
pub field: String,
pub test: bool,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct StructExpr {
pub type_name: String,
pub entries: Vec<IdedEntryExpr>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct MapExpr {
pub entries: Vec<IdedEntryExpr>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ListExpr {
pub elements: Vec<IdedExpr>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct StructFieldExpr {
pub field: String,
pub value: IdedExpr,
pub optional: bool,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct MapEntryExpr {
pub key: IdedExpr,
pub value: IdedExpr,
pub optional: bool,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ComprehensionExpr {
pub iter_range: Box<IdedExpr>,
pub iter_var: String,
pub iter_var2: Option<String>,
pub accu_var: String,
pub accu_init: Box<IdedExpr>,
pub loop_cond: Box<IdedExpr>,
pub loop_step: Box<IdedExpr>,
pub result: Box<IdedExpr>,
}
#[derive(Debug, Default)]
pub struct SourceInfo {
offsets: BTreeMap<u64, OffsetRange>,
pub source: String,
}
impl SourceInfo {
pub fn add_offset(&mut self, id: u64, start: u32, stop: u32) {
self.offsets.insert(id, OffsetRange { start, stop });
}
pub fn offset_for(&self, id: u64) -> Option<(u32, u32)> {
self.offsets.get(&id).map(|range| (range.start, range.stop))
}
pub(crate) fn pos_for(&self, id: u64) -> Option<(isize, isize)> {
match self.offset_for(id) {
Some((start, _)) => {
let start = start as isize;
let mut offset = 0;
let mut line = 0;
for l in self.source.split_inclusive('\n') {
line += 1;
offset += l.len() as isize;
if start < offset {
return Some((line, start + (l.len() as isize) - offset + 1));
}
}
None
}
None => None,
}
}
pub fn snippet(&self, line: isize) -> Option<&str> {
self.source.lines().nth(line as usize)
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct OffsetRange {
pub start: u32,
pub stop: u32,
}