cl_ast/ast_impl/
weight_of.rs

1//! Approximates the size of an AST
2
3use std::mem::size_of_val;
4
5use crate::ast::*;
6use cl_structures::{intern::interned::Interned, span::Span};
7
8/// Approximates the size of an AST without including indirection (pointers) or padding
9pub trait WeightOf {
10    /// Approximates the size of a syntax tree without including pointer/indirection or padding.
11    fn weight_of(&self) -> usize;
12}
13
14impl WeightOf for File {
15    fn weight_of(&self) -> usize {
16        let Self { name, items } = self;
17        name.weight_of() + items.weight_of()
18    }
19}
20
21impl WeightOf for Attrs {
22    fn weight_of(&self) -> usize {
23        let Self { meta } = self;
24        meta.weight_of()
25    }
26}
27
28impl WeightOf for Meta {
29    fn weight_of(&self) -> usize {
30        let Self { name, kind } = self;
31        name.weight_of() + kind.weight_of()
32    }
33}
34
35impl WeightOf for MetaKind {
36    fn weight_of(&self) -> usize {
37        match self {
38            MetaKind::Plain => size_of_val(self),
39            MetaKind::Equals(v) => v.weight_of(),
40            MetaKind::Func(v) => v.weight_of(),
41        }
42    }
43}
44
45impl WeightOf for Item {
46    fn weight_of(&self) -> usize {
47        let Self { span, attrs, vis, kind } = self;
48        span.weight_of() + attrs.weight_of() + vis.weight_of() + kind.weight_of()
49    }
50}
51
52impl WeightOf for ItemKind {
53    fn weight_of(&self) -> usize {
54        match self {
55            ItemKind::Module(v) => v.weight_of(),
56            ItemKind::Alias(v) => v.weight_of(),
57            ItemKind::Enum(v) => v.weight_of(),
58            ItemKind::Struct(v) => v.weight_of(),
59            ItemKind::Const(v) => v.weight_of(),
60            ItemKind::Static(v) => v.weight_of(),
61            ItemKind::Function(v) => v.weight_of(),
62            ItemKind::Impl(v) => v.weight_of(),
63            ItemKind::Use(v) => v.weight_of(),
64        }
65    }
66}
67
68impl WeightOf for Generics {
69    fn weight_of(&self) -> usize {
70        let Self { vars } = self;
71        vars.iter().map(|v| v.weight_of()).sum()
72    }
73}
74
75impl WeightOf for Module {
76    fn weight_of(&self) -> usize {
77        let Self { name, file } = self;
78        name.weight_of() + file.weight_of()
79    }
80}
81
82impl WeightOf for Alias {
83    fn weight_of(&self) -> usize {
84        let Self { name, from } = self;
85        name.weight_of() + from.weight_of()
86    }
87}
88
89impl WeightOf for Const {
90    fn weight_of(&self) -> usize {
91        let Self { name, ty, init } = self;
92        name.weight_of() + ty.weight_of() + init.weight_of()
93    }
94}
95
96impl WeightOf for Static {
97    fn weight_of(&self) -> usize {
98        let Self { mutable, name, ty, init } = self;
99        mutable.weight_of() + name.weight_of() + ty.weight_of() + init.weight_of()
100    }
101}
102
103impl WeightOf for Function {
104    fn weight_of(&self) -> usize {
105        let Self { name, gens, sign, bind, body } = self;
106        name.weight_of() + gens.weight_of() + sign.weight_of() + bind.weight_of() + body.weight_of()
107    }
108}
109
110impl WeightOf for Struct {
111    fn weight_of(&self) -> usize {
112        let Self { name, gens, kind } = self;
113        name.weight_of() + gens.weight_of() + kind.weight_of()
114    }
115}
116
117impl WeightOf for StructKind {
118    fn weight_of(&self) -> usize {
119        match self {
120            StructKind::Empty => size_of_val(self),
121            StructKind::Tuple(items) => items.weight_of(),
122            StructKind::Struct(sm) => sm.weight_of(),
123        }
124    }
125}
126
127impl WeightOf for StructMember {
128    fn weight_of(&self) -> usize {
129        let Self { vis, name, ty } = self;
130        vis.weight_of() + name.weight_of() + ty.weight_of()
131    }
132}
133
134impl WeightOf for Enum {
135    fn weight_of(&self) -> usize {
136        let Self { name, gens, variants } = self;
137        name.weight_of() + gens.weight_of() + variants.weight_of()
138    }
139}
140
141impl WeightOf for Variant {
142    fn weight_of(&self) -> usize {
143        let Self { name, kind, body } = self;
144        name.weight_of() + kind.weight_of() + body.weight_of()
145    }
146}
147
148impl WeightOf for Impl {
149    fn weight_of(&self) -> usize {
150        let Self { gens, target, body } = self;
151        gens.weight_of() + target.weight_of() + body.weight_of()
152    }
153}
154
155impl WeightOf for ImplKind {
156    fn weight_of(&self) -> usize {
157        match self {
158            ImplKind::Type(ty) => ty.weight_of(),
159            ImplKind::Trait { impl_trait, for_type } => {
160                impl_trait.weight_of() + for_type.weight_of()
161            }
162        }
163    }
164}
165
166impl WeightOf for Use {
167    fn weight_of(&self) -> usize {
168        let Self { absolute, tree } = self;
169        absolute.weight_of() + tree.weight_of()
170    }
171}
172
173impl WeightOf for UseTree {
174    fn weight_of(&self) -> usize {
175        match self {
176            UseTree::Tree(tr) => tr.weight_of(),
177            UseTree::Path(pa, tr) => pa.weight_of() + tr.weight_of(),
178            UseTree::Alias(src, dst) => src.weight_of() + dst.weight_of(),
179            UseTree::Name(src) => src.weight_of(),
180            UseTree::Glob => size_of_val(self),
181        }
182    }
183}
184
185impl WeightOf for Ty {
186    fn weight_of(&self) -> usize {
187        let Self { span, kind, gens } = self;
188        span.weight_of() + kind.weight_of() + gens.weight_of()
189    }
190}
191
192impl WeightOf for TyKind {
193    fn weight_of(&self) -> usize {
194        match self {
195            TyKind::Never | TyKind::Infer => size_of_val(self),
196            TyKind::Path(v) => v.weight_of(),
197            TyKind::Array(v) => v.weight_of(),
198            TyKind::Slice(v) => v.weight_of(),
199            TyKind::Tuple(v) => v.weight_of(),
200            TyKind::Ref(v) => v.weight_of(),
201            TyKind::Ptr(v) => v.weight_of(),
202            TyKind::Fn(v) => v.weight_of(),
203        }
204    }
205}
206
207impl WeightOf for TyArray {
208    fn weight_of(&self) -> usize {
209        let Self { ty, count } = self;
210        ty.weight_of() + count.weight_of()
211    }
212}
213
214impl WeightOf for TySlice {
215    fn weight_of(&self) -> usize {
216        let Self { ty } = self;
217        ty.weight_of()
218    }
219}
220
221impl WeightOf for TyTuple {
222    fn weight_of(&self) -> usize {
223        let Self { types } = self;
224        types.weight_of()
225    }
226}
227
228impl WeightOf for TyRef {
229    fn weight_of(&self) -> usize {
230        let Self { mutable, count, to } = self;
231        mutable.weight_of() + count.weight_of() + to.weight_of()
232    }
233}
234
235impl WeightOf for TyPtr {
236    fn weight_of(&self) -> usize {
237        let Self { to } = self;
238        to.weight_of()
239    }
240}
241
242impl WeightOf for TyFn {
243    fn weight_of(&self) -> usize {
244        let Self { args, rety } = self;
245        args.weight_of() + rety.weight_of()
246    }
247}
248
249impl WeightOf for Path {
250    fn weight_of(&self) -> usize {
251        let Self { absolute, parts } = self;
252        absolute.weight_of() + parts.weight_of()
253    }
254}
255
256impl WeightOf for PathPart {
257    fn weight_of(&self) -> usize {
258        match self {
259            PathPart::SuperKw => size_of_val(self),
260            PathPart::SelfTy => size_of_val(self),
261            PathPart::Ident(interned) => interned.weight_of(),
262        }
263    }
264}
265
266impl WeightOf for Stmt {
267    fn weight_of(&self) -> usize {
268        let Self { span, kind, semi } = self;
269        span.weight_of() + kind.weight_of() + semi.weight_of()
270    }
271}
272
273impl WeightOf for StmtKind {
274    fn weight_of(&self) -> usize {
275        match self {
276            StmtKind::Empty => size_of_val(self),
277            StmtKind::Item(item) => item.weight_of(),
278            StmtKind::Expr(expr) => expr.weight_of(),
279        }
280    }
281}
282
283impl WeightOf for Expr {
284    fn weight_of(&self) -> usize {
285        let Self { span, kind } = self;
286        span.weight_of() + kind.weight_of()
287    }
288}
289
290impl WeightOf for ExprKind {
291    fn weight_of(&self) -> usize {
292        match self {
293            ExprKind::Empty => size_of_val(self),
294            ExprKind::Closure(v) => v.weight_of(),
295            ExprKind::Quote(v) => v.weight_of(),
296            ExprKind::Let(v) => v.weight_of(),
297            ExprKind::Match(v) => v.weight_of(),
298            ExprKind::Assign(v) => v.weight_of(),
299            ExprKind::Modify(v) => v.weight_of(),
300            ExprKind::Binary(v) => v.weight_of(),
301            ExprKind::Unary(v) => v.weight_of(),
302            ExprKind::Cast(v) => v.weight_of(),
303            ExprKind::Member(v) => v.weight_of(),
304            ExprKind::Index(v) => v.weight_of(),
305            ExprKind::Structor(v) => v.weight_of(),
306            ExprKind::Path(v) => v.weight_of(),
307            ExprKind::Literal(v) => v.weight_of(),
308            ExprKind::Array(v) => v.weight_of(),
309            ExprKind::ArrayRep(v) => v.weight_of(),
310            ExprKind::AddrOf(v) => v.weight_of(),
311            ExprKind::Block(v) => v.weight_of(),
312            ExprKind::Group(v) => v.weight_of(),
313            ExprKind::Tuple(v) => v.weight_of(),
314            ExprKind::While(v) => v.weight_of(),
315            ExprKind::If(v) => v.weight_of(),
316            ExprKind::For(v) => v.weight_of(),
317            ExprKind::Break(v) => v.weight_of(),
318            ExprKind::Return(v) => v.weight_of(),
319            ExprKind::Continue => size_of_val(self),
320        }
321    }
322}
323
324impl WeightOf for Closure {
325    fn weight_of(&self) -> usize {
326        let Self { arg, body } = self;
327        arg.weight_of() + body.weight_of()
328    }
329}
330
331impl WeightOf for Quote {
332    fn weight_of(&self) -> usize {
333        let Self { quote } = self;
334        quote.weight_of()
335    }
336}
337
338impl WeightOf for Let {
339    fn weight_of(&self) -> usize {
340        let Self { mutable, name, ty, init } = self;
341        mutable.weight_of() + name.weight_of() + ty.weight_of() + init.weight_of()
342    }
343}
344
345impl WeightOf for Pattern {
346    fn weight_of(&self) -> usize {
347        match self {
348            Pattern::Name(s) => size_of_val(s),
349            Pattern::Path(p) => p.weight_of(),
350            Pattern::Literal(literal) => literal.weight_of(),
351            Pattern::Rest(Some(pattern)) => pattern.weight_of(),
352            Pattern::Rest(None) => 0,
353            Pattern::Ref(mutability, pattern) => mutability.weight_of() + pattern.weight_of(),
354            Pattern::RangeExc(head, tail) => head.weight_of() + tail.weight_of(),
355            Pattern::RangeInc(head, tail) => head.weight_of() + tail.weight_of(),
356            Pattern::Tuple(patterns) | Pattern::Array(patterns) => patterns.weight_of(),
357            Pattern::Struct(path, items) => {
358                let sitems: usize = items
359                    .iter()
360                    .map(|(name, opt)| name.weight_of() + opt.weight_of())
361                    .sum();
362                path.weight_of() + sitems
363            }
364            Pattern::TupleStruct(path, patterns) => path.weight_of() + patterns.weight_of(),
365        }
366    }
367}
368
369impl WeightOf for Match {
370    fn weight_of(&self) -> usize {
371        let Self { scrutinee, arms } = self;
372        scrutinee.weight_of() + arms.weight_of()
373    }
374}
375
376impl WeightOf for MatchArm {
377    fn weight_of(&self) -> usize {
378        let Self(pattern, expr) = self;
379        pattern.weight_of() + expr.weight_of()
380    }
381}
382
383impl WeightOf for Assign {
384    fn weight_of(&self) -> usize {
385        let Self { parts } = self;
386
387        parts.0.weight_of() + parts.1.weight_of()
388    }
389}
390
391impl WeightOf for Modify {
392    #[rustfmt::skip]
393    fn weight_of(&self) -> usize {
394        let Self { kind, parts } = self;
395        kind.weight_of()
396            + parts.0.weight_of()
397            + parts.1.weight_of()
398    }
399}
400
401impl WeightOf for Binary {
402    fn weight_of(&self) -> usize {
403        let Self { kind, parts } = self;
404
405        kind.weight_of() + parts.0.weight_of() + parts.1.weight_of()
406    }
407}
408
409impl WeightOf for Unary {
410    #[rustfmt::skip]
411    fn weight_of(&self) -> usize {
412        let Self { kind, tail } = self;
413         kind.weight_of() + tail.weight_of()
414    }
415}
416
417impl WeightOf for Cast {
418    fn weight_of(&self) -> usize {
419        let Self { head, ty } = self;
420        head.weight_of() + ty.weight_of()
421    }
422}
423
424impl WeightOf for Member {
425    fn weight_of(&self) -> usize {
426        let Self { head, kind } = self;
427
428        head.weight_of() + kind.weight_of() // accounting
429    }
430}
431
432impl WeightOf for MemberKind {
433    fn weight_of(&self) -> usize {
434        match self {
435            MemberKind::Call(_, tuple) => tuple.weight_of(),
436            MemberKind::Struct(_) => 0,
437            MemberKind::Tuple(literal) => literal.weight_of(),
438        }
439    }
440}
441
442impl WeightOf for Index {
443    fn weight_of(&self) -> usize {
444        let Self { head, indices } = self;
445        head.weight_of() + indices.weight_of()
446    }
447}
448
449impl WeightOf for Literal {
450    fn weight_of(&self) -> usize {
451        match self {
452            Literal::Bool(v) => v.weight_of(),
453            Literal::Char(v) => v.weight_of(),
454            Literal::Int(v) => v.weight_of(),
455            Literal::Float(v) => v.weight_of(),
456            Literal::String(v) => v.weight_of(),
457        }
458    }
459}
460
461impl WeightOf for Structor {
462    fn weight_of(&self) -> usize {
463        let Self { to, init } = self;
464        to.weight_of() + init.weight_of()
465    }
466}
467
468impl WeightOf for Fielder {
469    fn weight_of(&self) -> usize {
470        let Self { name, init } = self;
471        name.weight_of() + init.weight_of()
472    }
473}
474
475impl WeightOf for Array {
476    fn weight_of(&self) -> usize {
477        let Self { values } = self;
478        values.weight_of()
479    }
480}
481
482impl WeightOf for ArrayRep {
483    fn weight_of(&self) -> usize {
484        let Self { value, repeat } = self;
485        value.weight_of() + repeat.weight_of()
486    }
487}
488
489impl WeightOf for AddrOf {
490    fn weight_of(&self) -> usize {
491        let Self { mutable, expr } = self;
492        mutable.weight_of() + expr.weight_of()
493    }
494}
495
496impl WeightOf for Block {
497    fn weight_of(&self) -> usize {
498        let Self { stmts } = self;
499        stmts.weight_of()
500    }
501}
502
503impl WeightOf for Group {
504    fn weight_of(&self) -> usize {
505        let Self { expr } = self;
506        expr.weight_of()
507    }
508}
509
510impl WeightOf for Tuple {
511    fn weight_of(&self) -> usize {
512        let Self { exprs } = self;
513        exprs.weight_of()
514    }
515}
516
517impl WeightOf for While {
518    fn weight_of(&self) -> usize {
519        let Self { cond, pass, fail } = self;
520        cond.weight_of() + pass.weight_of() + fail.weight_of()
521    }
522}
523
524impl WeightOf for If {
525    fn weight_of(&self) -> usize {
526        let Self { cond, pass, fail } = self;
527        cond.weight_of() + pass.weight_of() + fail.weight_of()
528    }
529}
530
531impl WeightOf for For {
532    fn weight_of(&self) -> usize {
533        let Self { bind, cond, pass, fail } = self;
534        bind.weight_of() + cond.weight_of() + pass.weight_of() + fail.weight_of()
535    }
536}
537
538impl WeightOf for Else {
539    fn weight_of(&self) -> usize {
540        let Self { body } = self;
541        body.weight_of()
542    }
543}
544
545impl WeightOf for Break {
546    fn weight_of(&self) -> usize {
547        let Self { body } = self;
548        body.weight_of()
549    }
550}
551
552impl WeightOf for Return {
553    fn weight_of(&self) -> usize {
554        let Self { body } = self;
555        body.weight_of()
556    }
557}
558
559// ------------ SizeOf Blanket Implementations
560
561impl<T: WeightOf> WeightOf for Option<T> {
562    fn weight_of(&self) -> usize {
563        match self {
564            Some(t) => t.weight_of().max(size_of_val(t)),
565            None => size_of_val(self),
566        }
567    }
568}
569
570impl<T: WeightOf> WeightOf for [T] {
571    fn weight_of(&self) -> usize {
572        self.iter().map(WeightOf::weight_of).sum()
573    }
574}
575
576impl<T: WeightOf> WeightOf for Vec<T> {
577    fn weight_of(&self) -> usize {
578        size_of::<Self>() + self.iter().map(WeightOf::weight_of).sum::<usize>()
579    }
580}
581
582impl<T: WeightOf> WeightOf for Box<T> {
583    fn weight_of(&self) -> usize {
584        (**self).weight_of() + size_of::<Self>()
585    }
586}
587
588impl WeightOf for str {
589    fn weight_of(&self) -> usize {
590        self.len()
591    }
592}
593
594impl_size_of! {
595    // primitives
596    u8, u16, u32, u64, u128, usize,
597    i8, i16, i32, i64, i128, isize,
598    f32, f64, bool, char,
599    // cl-structures
600    Span,
601    // cl-ast
602    Visibility, Mutability, Semi, ModifyKind, BinaryKind, UnaryKind
603}
604
605impl<T> WeightOf for Interned<'_, T> {
606    fn weight_of(&self) -> usize {
607        size_of_val(self) // interned values are opaque to SizeOF
608    }
609}
610
611macro impl_size_of($($T:ty),*$(,)?) {
612    $(impl WeightOf for $T {
613        fn weight_of(&self) -> usize {
614            ::std::mem::size_of_val(self)
615        }
616    })*
617}