use std::mem;
use cljrs_types::span::Span;
#[derive(Debug, Clone)]
pub struct Form {
pub kind: FormKind,
pub span: Span,
}
impl Form {
pub fn new(kind: FormKind, span: Span) -> Self {
Self { kind, span }
}
pub fn heap_size(&self) -> usize {
mem::size_of::<FormKind>() + self.kind.heap_size()
}
}
impl FormKind {
pub fn heap_size(&self) -> usize {
match self {
FormKind::Nil
| FormKind::Bool(_)
| FormKind::Int(_)
| FormKind::Float(_)
| FormKind::Char(_)
| FormKind::Symbolic(_) => 0,
FormKind::BigInt(s)
| FormKind::BigDecimal(s)
| FormKind::Ratio(s)
| FormKind::Str(s)
| FormKind::Regex(s)
| FormKind::Symbol(s)
| FormKind::Keyword(s)
| FormKind::AutoKeyword(s) => s.capacity(),
FormKind::List(v)
| FormKind::Vector(v)
| FormKind::Map(v)
| FormKind::Set(v)
| FormKind::AnonFn(v) => vec_heap_size(v),
FormKind::Quote(f)
| FormKind::SyntaxQuote(f)
| FormKind::Unquote(f)
| FormKind::UnquoteSplice(f)
| FormKind::Deref(f)
| FormKind::Var(f) => mem::size_of::<Form>() + f.heap_size(),
FormKind::Meta(a, b) => mem::size_of::<Form>() * 2 + a.heap_size() + b.heap_size(),
FormKind::TaggedLiteral(s, f) => s.capacity() + mem::size_of::<Form>() + f.heap_size(),
FormKind::ReaderCond { clauses, .. } => vec_heap_size(clauses),
}
}
}
impl PartialEq for Form {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum FormKind {
Nil,
Bool(bool),
Int(i64),
BigInt(String),
Float(f64), BigDecimal(String),
Ratio(String),
Char(char),
Str(String),
Regex(String),
Symbolic(f64),
Symbol(String),
Keyword(String),
AutoKeyword(String),
List(Vec<Form>),
Vector(Vec<Form>),
Map(Vec<Form>),
Set(Vec<Form>),
Quote(Box<Form>),
SyntaxQuote(Box<Form>),
Unquote(Box<Form>),
UnquoteSplice(Box<Form>),
Deref(Box<Form>),
Var(Box<Form>),
Meta(Box<Form>, Box<Form>),
AnonFn(Vec<Form>),
TaggedLiteral(String, Box<Form>),
ReaderCond {
splicing: bool,
clauses: Vec<Form>,
},
}
fn vec_heap_size(forms: &[Form]) -> usize {
mem::size_of_val(forms) + forms.iter().map(|f| f.heap_size()).sum::<usize>()
}