Skip to main content

geo_aid_script/
unroll.rs

1//! The unroll step is where syntatic sugars are extended, type checks made
2//! and general script validity is checked. Technically, a script that makes
3//! it past unrolling is elligible to directly compiling and generating with
4//! no in-between steps.
5//!
6//! This is also where all information on how to handle the figure is extracted.
7
8use crate::{parser, span};
9use flags::FlagSetConstructor;
10use geo_aid_derive::CloneWithNode;
11use geo_aid_figure::Style;
12use num_traits::{One, Zero};
13use std::any::Any;
14use std::fmt::Formatter;
15use std::mem;
16use std::{
17    collections::{hash_map::Entry, HashMap},
18    fmt::{Debug, Display},
19    hash::Hash,
20    ops::{Deref, DerefMut},
21    rc::Rc,
22    write,
23};
24
25use crate::figure::SpannedMathString;
26use crate::ty;
27use library::macros::index;
28
29use self::context::CompileContext;
30use self::figure::{
31    AnyExprNode, CircleNode, CollectionNode, EmptyNode, FromExpr, HierarchyNode, LineNode,
32    LineType, MaybeUnset, Node, NumberNode, PCNode, PointNode,
33};
34use self::library::Library;
35
36use super::parser::{
37    ExprBinop, ExprCall, FromProperty, InputStream, Name, PointCollectionConstructor, RefStatement,
38};
39use super::token::number::{CompExponent, ProcNum};
40use super::token::NumberLit;
41use super::{
42    parser::{
43        BinaryOperator, DisplayProperties, ExplicitIterator, Expression, ImplicitIterator,
44        LetStatement, Parse, PredefinedRuleOperator, PropertyValue, Punctuated, RuleOperator,
45        RuleStatement, SimpleExpression, SimpleExpressionKind, Statement, Type,
46    },
47    token::{self, Ident, NamedIdent, PointCollection as PCToken, Span},
48    unit, ComplexUnit, Error,
49};
50
51pub mod context;
52pub mod figure;
53pub mod flags;
54pub mod library;
55
56/// A helper trait for unrolling syntax nodes.
57trait Unroll<T = AnyExpr> {
58    fn unroll(
59        &self,
60        context: &mut CompileContext,
61        library: &Library,
62        it_index: &HashMap<u8, usize>,
63        display: Properties,
64    ) -> T;
65}
66
67/// A definition for a user-defined rule operator.
68#[derive(Debug)]
69pub struct RuleOperatorDefinition {
70    /// Operator's name.
71    pub name: String,
72}
73
74/// A variable created with a let statement.
75#[derive(Debug)]
76pub struct Variable<T: Displayed> {
77    /// Variable's name
78    pub name: String,
79    /// Variable's definition span.
80    pub definition_span: Span,
81    /// Variable's definition.
82    pub definition: Expr<T>,
83}
84
85/// Represents complicated iterator structures.
86#[derive(Debug)]
87pub struct IterTree {
88    /// The variants of the top-level iterator.
89    pub variants: Vec<IterNode>,
90    /// The id of the top-level iterator.
91    pub id: u8,
92    /// The span of the top-level iterator.
93    pub span: Span,
94}
95
96/// A single node of `IterTree`. Might have parallel iterator children.
97/// `IterNode`s represent single iterator variants.
98#[derive(Debug)]
99pub struct IterNode(Vec<IterTree>);
100
101impl Deref for IterNode {
102    type Target = Vec<IterTree>;
103
104    fn deref(&self) -> &Self::Target {
105        &self.0
106    }
107}
108
109impl DerefMut for IterNode {
110    fn deref_mut(&mut self) -> &mut Self::Target {
111        &mut self.0
112    }
113}
114
115impl<const ITER: bool> From<&Expression<ITER>> for IterNode {
116    fn from(value: &Expression<ITER>) -> Self {
117        match value {
118            Expression::ImplicitIterator(it) => it.into(),
119            Expression::Binop(binop) => Self::from2(binop.lhs.as_ref(), binop.rhs.as_ref()),
120        }
121    }
122}
123
124impl From<&SimpleExpressionKind> for IterNode {
125    fn from(value: &SimpleExpressionKind) -> Self {
126        match value {
127            SimpleExpressionKind::Number(_) => IterNode::new(Vec::new()),
128            SimpleExpressionKind::Name(name) => name.into(),
129            SimpleExpressionKind::ExplicitIterator(it) => IterNode::new(vec![it.into()]),
130            SimpleExpressionKind::PointCollection(col) => IterNode::new(
131                col.points
132                    .iter()
133                    .flat_map(|v| IterNode::from(v).0.into_iter())
134                    .collect(),
135            ),
136        }
137    }
138}
139
140impl From<&Name> for IterNode {
141    fn from(value: &Name) -> Self {
142        match value {
143            Name::Ident(_) => IterNode::new(Vec::new()),
144            Name::FieldIndex(f) => f.name.as_ref().into(),
145            Name::Call(expr) => IterNode::new(
146                IterNode::from(expr.name.as_ref())
147                    .0
148                    .into_iter()
149                    .chain(
150                        expr.params
151                            .as_ref()
152                            .into_iter()
153                            .flat_map(|params| params.iter().flat_map(|v| IterNode::from(v).0)),
154                    )
155                    .collect(),
156            ),
157            Name::Expression(expr) => expr.content.as_ref().into(),
158        }
159    }
160}
161
162impl<const ITER: bool> From<&ImplicitIterator<ITER>> for IterNode {
163    fn from(value: &ImplicitIterator<ITER>) -> Self {
164        if value.exprs.collection.is_empty() {
165            (&value.exprs.first.as_ref().kind).into()
166        } else {
167            IterNode::new(vec![value.into()])
168        }
169    }
170}
171
172impl<const ITER: bool> From<&ImplicitIterator<ITER>> for IterTree {
173    fn from(value: &ImplicitIterator<ITER>) -> Self {
174        Self {
175            id: 0, // Implicit iterators have an id of 0.
176            variants: value.exprs.iter().map(|v| (&v.kind).into()).collect(),
177            span: value.get_span(),
178        }
179    }
180}
181
182impl From<&ExplicitIterator> for IterTree {
183    fn from(value: &ExplicitIterator) -> Self {
184        Self {
185            id: value.id,
186            variants: value.exprs.iter().map(IterNode::from).collect(),
187            span: value.get_span(),
188        }
189    }
190}
191
192impl IterTree {
193    /// Collect lengths of each iterator mapped to the iterators' ids.
194    ///
195    /// # Errors
196    /// Returns an error when there is an inconsistency in among iterators (same id, different lengths)
197    /// or when an iterator with id x contains an iterator with id x.
198    pub fn get_iter_lengths(
199        &self,
200        lengths: &mut HashMap<u8, (usize, Span, Option<Span>)>,
201        full_span: Span,
202    ) -> Result<(), Error> {
203        for variant in &self.variants {
204            variant.get_iter_lengths(lengths, full_span)?;
205        }
206
207        Ok(())
208    }
209}
210
211impl IterNode {
212    /// Create an empty iterator tree node.
213    #[must_use]
214    pub fn new(content: Vec<IterTree>) -> Self {
215        Self(content)
216    }
217
218    /// Create an iterator node from two expressions. Used in binary operation unrolling.
219    #[must_use]
220    pub fn from2<const ITER1: bool, const ITER2: bool>(
221        e1: &Expression<ITER1>,
222        e2: &Expression<ITER2>,
223    ) -> Self {
224        let mut node = Self::from(e1);
225        node.extend(Self::from(e2).0);
226        node
227    }
228
229    /// Collect lengths of each iterator mapped to the iterators' ids.
230    ///
231    /// # Panics
232    /// Never.
233    ///
234    /// # Errors
235    /// Returns an error when there is an inconsistency in among iterators (same id, different lengths)
236    /// or when an iterator with id x contains an iterator with id x.
237    pub fn get_iter_lengths(
238        &self,
239        lengths: &mut HashMap<u8, (usize, Span, Option<Span>)>,
240        full_span: Span,
241    ) -> Result<(), Error> {
242        for iter in &self.0 {
243            match lengths.entry(iter.id) {
244                Entry::Vacant(entry) => {
245                    entry.insert((iter.variants.len(), iter.span, Some(iter.span)));
246                }
247                Entry::Occupied(mut entry) => {
248                    if entry.get().0 != iter.variants.len() {
249                        return Err(Error::InconsistentIterators {
250                            first_span: entry.get().1,
251                            first_length: entry.get().0,
252                            occurred_span: iter.span,
253                            occurred_length: iter.variants.len(),
254                            error_span: full_span,
255                        });
256                    } else if let Some(parent) = entry.get().2 {
257                        return Err(Error::IteratorWithSameIdIterator {
258                            error_span: full_span,
259                            parent_span: parent,
260                            contained_span: iter.span,
261                        });
262                    }
263
264                    entry.get_mut().2 = Some(iter.span);
265                }
266            }
267
268            iter.get_iter_lengths(lengths, full_span)?;
269            lengths.get_mut(&iter.id).unwrap().2 = None;
270        }
271
272        Ok(())
273    }
274}
275
276/// A range-like iterator, except multidimensional. This in an iterator
277/// in Rust's sense, not in `GeoScript`'s sense.
278#[derive(Debug)]
279pub struct MultiRangeIterator {
280    /// The maximal indices.
281    /// Maximal indices are first non-valid indice.s
282    maxes: Vec<usize>,
283    /// Current range indices.
284    currents: Vec<usize>,
285}
286
287impl MultiRangeIterator {
288    /// Create a new iterator based on maximal indices.
289    #[must_use]
290    pub fn new(maxes: Vec<usize>) -> Self {
291        let l = maxes.len();
292
293        Self {
294            maxes,
295            currents: [0].repeat(l),
296        }
297    }
298
299    /// Increment the iterator.
300    pub fn increment(&mut self) -> Option<&Vec<usize>> {
301        self.increment_place(self.currents.len() - 1)
302    }
303
304    /// Increment the specific range.
305    fn increment_place(&mut self, at: usize) -> Option<&Vec<usize>> {
306        self.currents[at] += 1;
307
308        if self.currents[at] == self.maxes[at] {
309            self.currents[at] = 0;
310            if at == 0 {
311                None
312            } else {
313                self.increment_place(at - 1)
314            }
315        } else {
316            Some(&self.currents)
317        }
318    }
319
320    /// Get current range indices.
321    #[must_use]
322    pub fn get_currents(&self) -> &Vec<usize> {
323        &self.currents
324    }
325}
326
327/// An iterator (Rust) over iterator (`GeoScript`) variants.
328#[derive(Debug)]
329pub struct IterTreeIterator<'r> {
330    /// List of lists of parallel iterators with their ids, current indices and lengths.
331    steps: Vec<(Vec<(&'r IterTree, usize)>, MultiRangeIterator)>,
332    /// Current index of each iterator.
333    currents: Option<HashMap<u8, usize>>,
334}
335
336impl<'r> IterTreeIterator<'r> {
337    /// Create a new iterator from a single tree node.
338    #[must_use]
339    pub fn new(tree: &'r IterNode) -> Self {
340        let mut this = Self {
341            steps: Vec::new(),
342            currents: Some(HashMap::new()),
343        };
344
345        this.add_node(tree);
346
347        this
348    }
349
350    /// Add a iterator tree node.
351    fn add_node(&mut self, node: &'r IterNode) {
352        if node.len() > 0 {
353            let mut visited = Vec::new();
354            let mut lengths = Vec::new();
355
356            for tree in node.iter() {
357                if !visited.contains(&tree.id) {
358                    visited.push(tree.id);
359                    lengths.push(tree.variants.len());
360                }
361            }
362
363            self.steps.push((
364                // `visited` will be in order. We can use that.
365                node.iter()
366                    .map(|v| {
367                        (
368                            v,
369                            visited
370                                .iter()
371                                .enumerate()
372                                .find(|(_, x)| **x == v.id)
373                                .unwrap()
374                                .0,
375                        )
376                    })
377                    .collect(),
378                MultiRangeIterator::new(lengths),
379            ));
380            self.update_currents();
381
382            self.update_iterators();
383        }
384    }
385
386    /// Update all iterators.
387    fn update_iterators(&mut self) {
388        let nodes = if let Some(node) = self.steps.last() {
389            node.0
390                .iter()
391                .map(|iter| &iter.0.variants[node.1.get_currents()[iter.1]])
392                .collect()
393        } else {
394            Vec::new()
395        };
396
397        for node in nodes {
398            self.add_node(node);
399        }
400    }
401
402    /// Update current indices.
403    fn update_currents(&mut self) {
404        let node = self.steps.last().unwrap();
405        let currents = node.1.get_currents();
406
407        for v in &node.0 {
408            self.currents
409                .as_mut()
410                .unwrap()
411                .entry(v.0.id)
412                .and_modify(|x| *x = currents[v.1])
413                .or_insert(currents[v.1]);
414        }
415    }
416
417    /// Increment this iterator.
418    pub fn next(&mut self) {
419        while let Some(node) = self.steps.last_mut() {
420            if node.1.increment().is_some() {
421                self.update_currents();
422                self.update_iterators();
423                return;
424            }
425
426            self.steps.pop();
427        }
428
429        self.currents = None;
430    }
431
432    /// Get current iterator indices.
433    #[must_use]
434    pub fn get_currents(&self) -> Option<&HashMap<u8, usize>> {
435        self.currents.as_ref()
436    }
437}
438
439/// The kind on the unrolled rule.
440#[derive(Debug)]
441pub enum UnrolledRuleKind {
442    /// A point equality rule (distance of 0)
443    PointEq(Expr<Point>, Expr<Point>),
444    /// A scalar equality
445    NumberEq(Expr<Number>, Expr<Number>),
446    /// a > b
447    Gt(Expr<Number>, Expr<Number>),
448    /// One of the rules must be true.
449    Alternative(Vec<UnrolledRule>),
450    /// Bias entities in an expression. Can alter behavior of some engines.
451    Bias(AnyExpr),
452}
453
454/// Helper trait for unrolled expression conversions.
455pub trait ConvertFrom<T>: Displayed {
456    /// Convert a value to `Self`.
457    ///
458    /// # Errors
459    /// Returns an error if the conversion is invalid.
460    fn convert_from(value: T, context: &CompileContext) -> Expr<Self>;
461
462    /// Check if conversion from a value to `Self` can be made.
463    fn can_convert_from(value: &T) -> bool;
464}
465
466/// Helper trait for unrolled expression conversions. Automatically implemented.
467/// Kinda like `Into`
468pub trait Convert
469where
470    Self: Sized,
471{
472    /// Convert `self` into a specific type.
473    ///
474    /// # Errors
475    /// Returns an error if the conversion is invalid.
476    fn convert<T: ConvertFrom<Self>>(self, context: &CompileContext) -> Expr<T>;
477
478    /// Check if `self` can be converted into a specific type.
479    ///
480    /// # Errors
481    /// Returns an error if the conversion is invalid.
482    fn can_convert<T: ConvertFrom<Self>>(&self) -> bool;
483}
484
485impl<T> Convert for T {
486    fn convert<U: ConvertFrom<Self>>(self, context: &CompileContext) -> Expr<U> {
487        U::convert_from(self, context)
488    }
489
490    fn can_convert<U: ConvertFrom<Self>>(&self) -> bool {
491        U::can_convert_from(self)
492    }
493}
494
495/// Helper trait for getting the type of a value.
496pub trait GetValueType {
497    fn get_value_type(&self) -> Type;
498}
499
500/// Helper trait for Geo-AID type representations.
501pub trait GeoType: From<Expr<Self::Target>> {
502    /// The target Geo-AID type this type can be converted to.
503    type Target: ConvertFrom<AnyExpr>;
504
505    fn get_type() -> Type;
506}
507
508macro_rules! impl_x_from_x {
509    ($what:ident) => {
510        impl ConvertFrom<Expr<$what>> for $what {
511            fn convert_from(value: Expr<$what>, _context: &CompileContext) -> Expr<Self> {
512                value
513            }
514
515            fn can_convert_from(_value: &Expr<$what>) -> bool {
516                true
517            }
518        }
519    };
520}
521
522macro_rules! impl_from_any {
523    ($what:ident) => {
524        impl ConvertFrom<AnyExpr> for $what {
525            fn convert_from(value: AnyExpr, context: &CompileContext) -> Expr<Self> {
526                match value {
527                    AnyExpr::Point(v) => v.convert(context),
528                    AnyExpr::Line(v) => v.convert(context),
529                    AnyExpr::Number(v) => v.convert(context),
530                    AnyExpr::Circle(v) => v.convert(context),
531                    AnyExpr::PointCollection(v) => v.convert(context),
532                    AnyExpr::Derived(v) => v.convert(context),
533                    AnyExpr::Unknown(v) => v.convert(context),
534                }
535            }
536
537            fn can_convert_from(value: &AnyExpr) -> bool {
538                match value {
539                    AnyExpr::Point(v) => Self::can_convert_from(v),
540                    AnyExpr::Line(v) => Self::can_convert_from(v),
541                    AnyExpr::Number(v) => Self::can_convert_from(v),
542                    AnyExpr::Circle(v) => Self::can_convert_from(v),
543                    AnyExpr::PointCollection(v) => Self::can_convert_from(v),
544                    AnyExpr::Derived(v) => Self::can_convert_from(v),
545                    AnyExpr::Unknown(v) => Self::can_convert_from(v),
546                }
547            }
548        }
549    };
550}
551
552macro_rules! convert_err {
553    ($from:ident($v:expr) -> $to:ident with $context:ident) => {{
554        let v = $v;
555
556        $context.push_error(Error::ImplicitConversionDoesNotExist {
557            error_span: v.span,
558            from: v.data.get_value_type(),
559            to: Self::get_type(),
560        });
561
562        Expr {
563            span: v.span,
564            data: Rc::new($to::dummy()),
565            node: None,
566        }
567    }};
568}
569
570macro_rules! impl_convert_err {
571    ($from:ident -> $to:ident) => {
572        impl ConvertFrom<Expr<$from>> for $to {
573            fn convert_from(value: Expr<$from>, context: &CompileContext) -> Expr<Self> {
574                convert_err!($from(value) -> $to with context)
575            }
576
577            fn can_convert_from(_value: &Expr<$from>) -> bool {
578                false
579            }
580        }
581    }
582}
583
584macro_rules! impl_from_unknown {
585    {$what:ident} => {
586        impl ConvertFrom<Expr<Unknown>> for $what {
587            fn convert_from(value: Expr<Unknown>, _context: &CompileContext) -> Expr<Self> {
588                Expr {
589                    span: value.span,
590                    data: Rc::new($what::dummy()),
591                    node: None
592                }
593            }
594
595            fn can_convert_from(_value: &Expr<Unknown>) -> bool {
596                true
597            }
598        }
599    }
600}
601
602macro_rules! impl_make_variable {
603    ($what:ident) => {
604        impl Expr<$what> {
605            #[must_use]
606            pub fn make_variable(self, name: String) -> Self {
607                let sp = self.span;
608
609                Expr {
610                    span: sp,
611                    data: Rc::new($what::Generic(Generic::VariableAccess(Rc::new(Variable {
612                        name,
613                        definition: self,
614                        definition_span: sp,
615                    })))),
616                    node: None, // Variable references are NEVER displayed
617                }
618            }
619        }
620    };
621    ($what:ident { other: $other:ident, data: $data:ident }) => {
622        impl Expr<$what> {
623            #[must_use]
624            pub fn make_variable(self, name: String) -> Self {
625                let sp = self.span;
626
627                Expr {
628                    span: sp,
629                    data: Rc::new($what {
630                        $other: self.data.$other,
631                        data: $data::Generic(Generic::VariableAccess(Rc::new(Variable {
632                            name,
633                            definition: self,
634                            definition_span: sp,
635                        }))),
636                    }),
637                    node: None, // Variable references are NEVER displayed
638                }
639            }
640        }
641    };
642}
643
644macro_rules! impl_any_from_x {
645    ($what:ident) => {
646        impl From<Expr<$what>> for AnyExpr {
647            fn from(value: Expr<$what>) -> Self {
648                AnyExpr::$what(value)
649            }
650        }
651    };
652}
653
654/// A generic expression, used with other types.
655#[derive(Debug, CloneWithNode)]
656pub enum Generic<T>
657where
658    T: Displayed,
659{
660    /// A reference to a variable.
661    VariableAccess(Rc<Variable<T>>),
662    /// A boxed expression. Used for artificial expression spanning.
663    Boxed(Expr<T>),
664    /// Dummy is a value specifically for continued unrolling after error occurrence.
665    /// It should never show up in compilation step.
666    Dummy,
667}
668
669impl<T: Display + Displayed> Display for Generic<T> {
670    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
671        match self {
672            Self::VariableAccess(name) => write!(f, "{}", name.name),
673            Self::Boxed(expr) => {
674                write!(f, "{expr}")
675            }
676            Self::Dummy => write!(f, "invalid (dummy)"),
677        }
678    }
679}
680
681/// An unrolled point expression
682#[derive(Debug, CloneWithNode)]
683pub enum Point {
684    /// A generic expression
685    Generic(Generic<Self>),
686    /// Arithmetic mean of points as complex numbers.
687    Average(ClonedVec<Expr<Point>>),
688    /// Intersection of two lines.
689    LineLineIntersection(Expr<Line>, Expr<Line>),
690    /// Center of a circle.
691    CircleCenter(Expr<Circle>),
692    /// A free point.
693    Free,
694    /// A point made from a complex number.
695    FromComplex(Expr<Number>),
696}
697
698impl Point {
699    #[must_use]
700    pub fn get_type() -> Type {
701        Type::Point
702    }
703}
704
705impl Dummy for Point {
706    fn dummy() -> Self {
707        Self::Generic(Generic::Dummy)
708    }
709
710    fn is_dummy(&self) -> bool {
711        matches!(self, Self::Generic(Generic::Dummy))
712    }
713}
714
715impl Displayed for Point {
716    type Node = PointNode;
717}
718
719impl GetData for Point {
720    fn get_data(&self) -> &Self {
721        match self {
722            Point::Generic(v) => match v {
723                Generic::Boxed(v) => v.get_data(),
724                Generic::VariableAccess(v) => v.definition.get_data(),
725                Generic::Dummy => self,
726            },
727            _ => self,
728        }
729    }
730}
731
732impl Expr<Point> {
733    /// Box this expression with a given span.
734    #[must_use]
735    pub fn boxed(mut self, span: Span) -> Self {
736        let node = self.node.take();
737
738        Self {
739            span,
740            data: Rc::new(Point::Generic(Generic::Boxed(self))),
741            node,
742        }
743    }
744
745    /// Get the point's x coordinate expression.
746    #[must_use]
747    pub fn x(self, span: Span, display: Properties, context: &CompileContext) -> Expr<Number> {
748        let mut expr = Expr {
749            span,
750            node: None,
751            data: Rc::new(Number {
752                unit: Some(unit::DISTANCE),
753                data: NumberData::PointX(self),
754            }),
755        };
756
757        expr.node = Some(HierarchyNode::from_expr(&expr, display, context));
758        expr
759    }
760
761    /// Get the point's y coordinate expression.
762    #[must_use]
763    pub fn y(self, span: Span, display: Properties, context: &CompileContext) -> Expr<Number> {
764        let mut expr = Expr {
765            span,
766            node: None,
767            data: Rc::new(Number {
768                unit: Some(unit::DISTANCE),
769                data: NumberData::PointY(self),
770            }),
771        };
772
773        expr.node = Some(HierarchyNode::from_expr(&expr, display, context));
774        expr
775    }
776}
777
778impl GeoType for Expr<Point> {
779    type Target = Point;
780
781    fn get_type() -> Type {
782        ty::POINT
783    }
784}
785
786impl GetValueType for Point {
787    fn get_value_type(&self) -> Type {
788        ty::POINT
789    }
790}
791
792impl Display for Point {
793    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
794        match self {
795            Self::Generic(v) => write!(f, "{v}"),
796            Self::Average(exprs) => write!(
797                f,
798                "average({})",
799                exprs
800                    .iter()
801                    .map(|v| format!("{v}"))
802                    .collect::<Vec<String>>()
803                    .join(", ")
804            ),
805            Self::LineLineIntersection(l1, l2) => {
806                write!(f, "intersection({l1}, {l2})")
807            }
808            Self::CircleCenter(circle) => {
809                write!(f, "{circle}.center")
810            }
811            Self::Free => write!(f, "Free point"),
812            Self::FromComplex(number) => write!(f, "to_point({number})"),
813        }
814    }
815}
816
817impl_x_from_x! {Point}
818impl_from_any! {Point}
819impl_from_unknown! {Point}
820impl_convert_err! {Circle -> Point}
821impl_convert_err! {Line -> Point}
822impl_convert_err! {Derived -> Point}
823impl_convert_err! {Number -> Point}
824
825impl_make_variable! {Point}
826
827impl ConvertFrom<Expr<PointCollection>> for Point {
828    fn convert_from(mut value: Expr<PointCollection>, context: &CompileContext) -> Expr<Self> {
829        if value.data.length == 1 {
830            let mut expr = index!(node value, 0);
831
832            if let Some(pc_node) = value.node {
833                if let Some(mut props) = pc_node.root.props {
834                    if let Some(pt_node) = &mut expr.node {
835                        pt_node.children = pc_node.children;
836                        pt_node.root.display = pc_node.root.display;
837
838                        pt_node.root.display_label = props.get("display_label").maybe_unset(true);
839                        pt_node.root.label = props
840                            .get("label")
841                            .maybe_unset(SpannedMathString::new(span!(0, 0, 0, 0)));
842                        pt_node.root.display_dot = props.get("display_dot").maybe_unset(true);
843                        pt_node.root.default_label = props
844                            .get("default-label")
845                            .ok_or(SpannedMathString::new(span!(0, 0, 0, 0)));
846                    }
847
848                    props.ignore("default-label");
849                    props.finish(context);
850                }
851            }
852
853            expr
854        } else {
855            convert_err!(PointCollection(value) -> Point with context)
856        }
857    }
858
859    fn can_convert_from(value: &Expr<PointCollection>) -> bool {
860        value.data.length == 1
861    }
862}
863
864/// An unrolled circle expression.
865#[derive(Debug, CloneWithNode)]
866pub enum Circle {
867    /// A generic expression
868    Generic(Generic<Self>),
869    /// A circle constructed from its center and radius.
870    Circle(Expr<Point>, Expr<Number>),
871}
872
873impl_x_from_x! {Circle}
874impl_from_any! {Circle}
875impl_from_unknown! {Circle}
876
877impl_convert_err! {Point -> Circle}
878impl_convert_err! {Line -> Circle}
879impl_convert_err! {Derived -> Circle}
880impl_convert_err! {Number -> Circle}
881impl_convert_err! {PointCollection -> Circle}
882
883impl_make_variable! {Circle}
884
885impl Circle {
886    #[must_use]
887    pub fn get_type() -> Type {
888        ty::CIRCLE
889    }
890}
891
892impl Dummy for Circle {
893    fn dummy() -> Self {
894        Self::Generic(Generic::Dummy)
895    }
896
897    fn is_dummy(&self) -> bool {
898        matches!(self, Self::Generic(Generic::Dummy))
899    }
900}
901
902impl Displayed for Circle {
903    type Node = CircleNode;
904}
905
906impl GetData for Circle {
907    fn get_data(&self) -> &Self {
908        match self {
909            Circle::Generic(v) => match v {
910                Generic::Boxed(v) => v.get_data(),
911                Generic::VariableAccess(v) => v.definition.get_data(),
912                Generic::Dummy => self,
913            },
914            Circle::Circle(..) => self,
915        }
916    }
917}
918
919impl Expr<Circle> {
920    /// Box this expression with a given span.
921    #[must_use]
922    pub fn boxed(mut self, span: Span) -> Self {
923        let node = self.node.take();
924
925        Self {
926            span,
927            data: Rc::new(Circle::Generic(Generic::Boxed(self))),
928            node,
929        }
930    }
931
932    /// Get the circle's center expression.
933    #[must_use]
934    pub fn center(self, span: Span, display: Properties, context: &CompileContext) -> Expr<Point> {
935        let mut expr = Expr {
936            span,
937            node: None,
938            data: Rc::new(Point::CircleCenter(self)),
939        };
940
941        expr.node = Some(HierarchyNode::from_expr(&expr, display, context));
942        expr
943    }
944
945    /// Get the circle's radius expression.
946    #[must_use]
947    pub fn radius(self, span: Span, display: Properties, context: &CompileContext) -> Expr<Number> {
948        let mut expr = Expr {
949            span,
950            node: None,
951            data: Rc::new(Number {
952                unit: Some(unit::DISTANCE),
953                data: NumberData::CircleRadius(self),
954            }),
955        };
956
957        expr.node = Some(HierarchyNode::from_expr(&expr, display, context));
958        expr
959    }
960}
961
962impl GetValueType for Circle {
963    fn get_value_type(&self) -> Type {
964        ty::CIRCLE
965    }
966}
967
968impl Display for Circle {
969    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
970        match self {
971            Self::Generic(v) => write!(f, "{v}"),
972            Self::Circle(center, radius) => {
973                write!(f, "circle({center}, {radius})")
974            }
975        }
976    }
977}
978
979impl GeoType for Expr<Circle> {
980    type Target = Circle;
981
982    fn get_type() -> Type {
983        ty::CIRCLE
984    }
985}
986/// An unrolled line expression.
987#[derive(Debug, CloneWithNode)]
988pub enum Line {
989    /// A generic expression
990    Generic(Generic<Self>),
991    /// A line going through two points.
992    LineFromPoints(Expr<Point>, Expr<Point>),
993    /// A bisector line of an angle defined by three points.
994    AngleBisector(Expr<Point>, Expr<Point>, Expr<Point>),
995    /// A line perpendicular to another one, going through a specific point
996    PerpendicularThrough(Expr<Line>, Expr<Point>),
997    /// A line perpendicular to another one, going through a specific point
998    ParallelThrough(Expr<Line>, Expr<Point>),
999    /// A line made from a point and a direction vector
1000    PointVector(Expr<Point>, Expr<Number>),
1001}
1002
1003impl Line {
1004    #[must_use]
1005    pub fn get_type() -> Type {
1006        ty::LINE
1007    }
1008}
1009
1010impl Dummy for Line {
1011    fn dummy() -> Self {
1012        Self::Generic(Generic::Dummy)
1013    }
1014
1015    fn is_dummy(&self) -> bool {
1016        matches!(self, Self::Generic(Generic::Dummy))
1017    }
1018}
1019
1020impl Displayed for Line {
1021    type Node = LineNode;
1022}
1023
1024impl GetData for Line {
1025    fn get_data(&self) -> &Self {
1026        match self {
1027            Line::Generic(v) => match v {
1028                Generic::Boxed(v) => v.get_data(),
1029                Generic::VariableAccess(v) => v.definition.get_data(),
1030                Generic::Dummy => self,
1031            },
1032            _ => self,
1033        }
1034    }
1035}
1036
1037impl Expr<Line> {
1038    /// Box the expression with a span.
1039    #[must_use]
1040    pub fn boxed(mut self, span: Span) -> Self {
1041        let node = self.node.take();
1042
1043        Self {
1044            span,
1045            data: Rc::new(Line::Generic(Generic::Boxed(self))),
1046            node,
1047        }
1048    }
1049}
1050
1051impl_x_from_x! {Line}
1052impl_from_any! {Line}
1053impl_from_unknown! {Line}
1054impl_convert_err! {Derived -> Line}
1055impl_convert_err! {Circle -> Line}
1056impl_convert_err! {Point -> Line}
1057impl_convert_err! {Number -> Line}
1058
1059impl_make_variable! {Line}
1060
1061impl ConvertFrom<Expr<PointCollection>> for Line {
1062    fn convert_from(mut value: Expr<PointCollection>, context: &CompileContext) -> Expr<Self> {
1063        if value.data.length == 2 {
1064            let mut expr = context.line(index!(node value, 0), index!(node value, 1));
1065            if let Some(pc_node) = value.node {
1066                if let Some(mut props) = pc_node.root.props {
1067                    if let Some(ln_node) = &mut expr.node {
1068                        ln_node.children = pc_node.children;
1069                        ln_node.root.display = pc_node.root.display;
1070
1071                        ln_node.root.display_label = props.get("display_label").maybe_unset(true);
1072                        ln_node.root.label = props
1073                            .get("label")
1074                            .maybe_unset(SpannedMathString::new(span!(0, 0, 0, 0)));
1075                        ln_node.root.default_label = props
1076                            .get("default-label")
1077                            .get_or(SpannedMathString::new(span!(0, 0, 0, 0)));
1078                        ln_node.root.style = props.get("style").maybe_unset(Style::default());
1079                        ln_node.root.line_type = props.get("type").maybe_unset(LineType::default());
1080                    }
1081
1082                    props.finish(context);
1083                }
1084            }
1085
1086            expr
1087        } else {
1088            convert_err!(PointCollection(value) -> Line with context)
1089        }
1090    }
1091
1092    fn can_convert_from(value: &Expr<PointCollection>) -> bool {
1093        value.data.length == 2
1094    }
1095}
1096
1097impl GetValueType for Line {
1098    fn get_value_type(&self) -> Type {
1099        ty::LINE
1100    }
1101}
1102
1103impl Display for Line {
1104    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1105        match self {
1106            Self::Generic(v) => write!(f, "{v}"),
1107            Self::LineFromPoints(e1, e2) => write!(f, "line({e1}, {e2})"),
1108            Self::AngleBisector(e1, e2, e3) => {
1109                write!(f, "angle-bisector({e1}, {e2}, {e3})")
1110            }
1111            Self::PerpendicularThrough(l, p) => {
1112                write!(f, "perpendicular-through({l}, {p})")
1113            }
1114            Self::ParallelThrough(l, p) => {
1115                write!(f, "parallel-through({l}, {p})")
1116            }
1117            Self::PointVector(p, v) => write!(f, "point-vector({p}, {v})"),
1118        }
1119    }
1120}
1121
1122impl GeoType for Expr<Line> {
1123    type Target = Line;
1124
1125    fn get_type() -> Type {
1126        ty::LINE
1127    }
1128}
1129
1130/// An unrolled number expression
1131#[derive(Debug, CloneWithNode)]
1132pub enum NumberData {
1133    /// A generic expression
1134    Generic(Generic<Number>),
1135    /// A constant
1136    Number(ProcNum),
1137    /// A distance literal not meant to be multiplied by the distance unit.
1138    DstLiteral(ProcNum),
1139    /// Override the expression's unit.
1140    SetUnit(Expr<Number>, ComplexUnit),
1141    /// Distance between two points.
1142    PointPointDistance(Expr<Point>, Expr<Point>),
1143    /// Distance of a point from a line.
1144    PointLineDistance(Expr<Point>, Expr<Line>),
1145    /// Minus expression
1146    Negate(Expr<Number>),
1147    /// a + b
1148    Add(Expr<Number>, Expr<Number>),
1149    /// a - b
1150    Subtract(Expr<Number>, Expr<Number>),
1151    /// a * b
1152    Multiply(Expr<Number>, Expr<Number>),
1153    /// a / b
1154    Divide(Expr<Number>, Expr<Number>),
1155    /// Angle defined by three points.
1156    ThreePointAngle(Expr<Point>, Expr<Point>, Expr<Point>),
1157    /// Directed angle defined by three points.
1158    ThreePointAngleDir(Expr<Point>, Expr<Point>, Expr<Point>),
1159    /// Angle between two lines.
1160    TwoLineAngle(Expr<Line>, Expr<Line>),
1161    /// The arithmetic mean of numbers.
1162    Average(ClonedVec<Expr<Number>>),
1163    /// Radius of a circle
1164    CircleRadius(Expr<Circle>),
1165    /// Raise a number to a power
1166    Pow(Expr<Number>, CompExponent),
1167    /// X coordinate of a point
1168    PointX(Expr<Point>),
1169    /// Y coordinate of a point
1170    PointY(Expr<Point>),
1171    /// A free number.
1172    Free,
1173    /// A point as a complex number
1174    FromPoint(Expr<Point>),
1175    /// Real part of a number
1176    Real(Expr<Number>),
1177    /// Imaginary part of a number
1178    Imaginary(Expr<Number>),
1179    /// Natural logarithm (base e)
1180    Log(Expr<Number>),
1181    /// Exp function (e^this)
1182    Exp(Expr<Number>),
1183    /// Sine
1184    Sin(Expr<Number>),
1185    /// Cosine
1186    Cos(Expr<Number>),
1187    /// Atan2
1188    Atan2(Expr<Number>, Expr<Number>),
1189    /// A line's direction vector
1190    Direction(Expr<Line>),
1191}
1192
1193impl Display for NumberData {
1194    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1195        match self {
1196            Self::Generic(v) => write!(f, "{v}"),
1197            Self::Average(exprs) => write!(
1198                f,
1199                "average({})",
1200                exprs
1201                    .iter()
1202                    .map(|v| format!("{v}"))
1203                    .collect::<Vec<String>>()
1204                    .join(", ")
1205            ),
1206            Self::Number(num) => write!(f, "{num}"),
1207            Self::DstLiteral(dst) => write!(f, "={dst}"),
1208            Self::SetUnit(expr, _) => {
1209                write!(f, "{expr}")
1210            }
1211            Self::PointPointDistance(e1, e2) => write!(f, "dst({e1}, {e2})"),
1212            Self::PointLineDistance(e1, e2) => write!(f, "dst({e1}, {e2})"),
1213            Self::Negate(e) => write!(f, "-{e}"),
1214            Self::Add(e1, e2) => write!(f, "{e1} + {e2}"),
1215            Self::Multiply(e1, e2) => write!(f, "{e1} * {e2}"),
1216            Self::Divide(e1, e2) => write!(f, "{e1} / {e2}"),
1217            Self::Subtract(e1, e2) => write!(f, "{e1} - {e2}"),
1218            Self::ThreePointAngle(e1, e2, e3) => {
1219                write!(f, "angle({e1}, {e2}, {e3})")
1220            }
1221            Self::ThreePointAngleDir(e1, e2, e3) => {
1222                write!(f, "dir_angle({e1}, {e2}, {e3})")
1223            }
1224            Self::TwoLineAngle(e1, e2) => write!(f, "angle({e1}, {e2})"),
1225            Self::CircleRadius(circle) => {
1226                write!(f, "{circle}.radius")
1227            }
1228            Self::Pow(base, exponent) => write!(f, "({base})^{exponent}"),
1229            Self::PointX(expr) => write!(f, "{expr}.x"),
1230            Self::PointY(expr) => write!(f, "{expr}.y"),
1231            Self::Free => write!(f, "Free scalar"),
1232            Self::FromPoint(point) => write!(f, "to_complex({point})"),
1233            Self::Real(number) => write!(f, "Re({number})"),
1234            Self::Imaginary(number) => write!(f, "Im({number})"),
1235            Self::Log(number) => write!(f, "log({number})"),
1236            Self::Exp(number) => write!(f, "exp({number})"),
1237            Self::Sin(v) => write!(f, "sin({v})"),
1238            Self::Cos(v) => write!(f, "cos({v})"),
1239            Self::Atan2(y, x) => write!(f, "atan2({y}, {x})"),
1240            Self::Direction(line) => write!(f, "dir({line})"),
1241        }
1242    }
1243}
1244
1245/// A scalar with a unit.
1246#[derive(Debug, CloneWithNode)]
1247pub struct Number {
1248    pub unit: Option<ComplexUnit>,
1249    pub data: NumberData,
1250}
1251
1252impl_x_from_x! {Number}
1253impl_from_any! {Number}
1254impl_from_unknown! {Number}
1255
1256impl_convert_err! {Point -> Number}
1257impl_convert_err! {Circle -> Number}
1258impl_convert_err! {Line -> Number}
1259impl_convert_err! {Derived -> Number}
1260
1261impl_make_variable! {Number {other: unit, data: NumberData}}
1262
1263impl Dummy for Number {
1264    fn dummy() -> Self {
1265        Self {
1266            unit: None,
1267            data: NumberData::Generic(Generic::Dummy),
1268        }
1269    }
1270
1271    fn is_dummy(&self) -> bool {
1272        matches!(self.data, NumberData::Generic(Generic::Dummy))
1273    }
1274}
1275
1276impl Displayed for Number {
1277    type Node = NumberNode;
1278}
1279
1280impl ConvertFrom<Expr<PointCollection>> for Number {
1281    fn convert_from(mut value: Expr<PointCollection>, context: &CompileContext) -> Expr<Self> {
1282        if value.data.length == 2 {
1283            // IMPORTANT: unwrap_or_else MUST be used to prevent
1284            // unnecessary props creation and drop errors.
1285            let display = value
1286                .node
1287                .as_mut()
1288                .and_then(|x| x.root.props.take())
1289                .unwrap_or_default();
1290
1291            let mut expr = library::dst::distance_function_pp(
1292                index!(node value, 0),
1293                index!(node value, 1),
1294                context,
1295                display,
1296            );
1297
1298            if let Some(pc_node) = value.node {
1299                if let Some(sc_node) = &mut expr.node {
1300                    sc_node.children = pc_node.children;
1301                    sc_node.root.display = pc_node.root.display;
1302                }
1303            }
1304
1305            expr.0
1306        } else {
1307            convert_err!(PointCollection(value) -> Number with context)
1308        }
1309    }
1310
1311    fn can_convert_from(value: &Expr<PointCollection>) -> bool {
1312        value.data.length == 2
1313    }
1314}
1315
1316impl Number {
1317    #[must_use]
1318    pub fn get_type() -> Type {
1319        ty::SCALAR
1320    }
1321}
1322
1323impl GetData for Number {
1324    fn get_data(&self) -> &Self {
1325        match &self.data {
1326            NumberData::Generic(v) => match v {
1327                Generic::Boxed(v) => v.get_data(),
1328                Generic::VariableAccess(v) => v.definition.get_data(),
1329                Generic::Dummy => self,
1330            },
1331            _ => self,
1332        }
1333    }
1334}
1335
1336impl Expr<Number> {
1337    /// Box the expression with a span.
1338    #[must_use]
1339    pub fn boxed(mut self, span: Span) -> Self {
1340        let node = self.node.take();
1341
1342        Self {
1343            span,
1344            data: Rc::new(Number {
1345                unit: self.data.unit,
1346                data: NumberData::Generic(Generic::Boxed(self)),
1347            }),
1348            node,
1349        }
1350    }
1351
1352    /// Try to convert this scalar to the given unit.
1353    ///
1354    /// # Errors
1355    /// Returns a conversion error if it is invalid.
1356    ///
1357    /// Only valid conversions are `None` to another unit or `self` to `self`
1358    #[must_use]
1359    pub fn convert_unit(mut self, unit: Option<ComplexUnit>, context: &CompileContext) -> Self {
1360        let err = Error::ImplicitConversionDoesNotExist {
1361            error_span: self.span,
1362            from: self.get_value_type(),
1363            to: Type::Number(unit),
1364        };
1365
1366        if self.data.unit == unit {
1367            self
1368        } else if unit.is_none() || self.data.unit.is_some() && self.data.unit != unit {
1369            context.push_error(err);
1370
1371            // And pretend the conversion is valid.
1372            Expr {
1373                span: self.span,
1374                data: Rc::new(Number {
1375                    unit,
1376                    data: self.data.data.clone_without_node(),
1377                }),
1378                node: self.node.take(),
1379            }
1380        } else {
1381            // `unit` is concrete and self.unit is not
1382            Self {
1383                data: Rc::new(Number {
1384                    unit,
1385                    data: match &self.data.data {
1386                        NumberData::Generic(generic) => match generic {
1387                            Generic::VariableAccess(_) => unreachable!(), // Always concrete
1388                            Generic::Boxed(v) => NumberData::Generic(Generic::Boxed(
1389                                v.clone_without_node().convert_unit(unit, context),
1390                            )),
1391                            Generic::Dummy => NumberData::Generic(Generic::Dummy),
1392                        },
1393                        v @ NumberData::Number(_) => v.clone_without_node(),
1394                        NumberData::Free => {
1395                            NumberData::SetUnit(self.clone_without_node(), unit.unwrap_or_default())
1396                        }
1397                        NumberData::DstLiteral(_)
1398                        | NumberData::PointPointDistance(_, _)
1399                        | NumberData::PointLineDistance(_, _)
1400                        | NumberData::ThreePointAngle(_, _, _)
1401                        | NumberData::ThreePointAngleDir(_, _, _)
1402                        | NumberData::TwoLineAngle(_, _)
1403                        | NumberData::CircleRadius(_)
1404                        | NumberData::PointX(_)
1405                        | NumberData::PointY(_)
1406                        | NumberData::Log(_)
1407                        | NumberData::Exp(_)
1408                        | NumberData::Sin(_)
1409                        | NumberData::Cos(_)
1410                        | NumberData::Atan2(_, _)
1411                        | NumberData::Direction(_)
1412                        | NumberData::FromPoint(_)
1413                        | NumberData::SetUnit(_, _) => unreachable!(), // Always concrete
1414                        NumberData::Negate(v) => {
1415                            NumberData::Negate(v.clone_without_node().convert_unit(unit, context))
1416                        }
1417                        NumberData::Add(a, b) => {
1418                            // Both operands are guaranteed to be unit-less here.
1419                            NumberData::Add(
1420                                a.clone_without_node().convert_unit(unit, context),
1421                                b.clone_without_node().convert_unit(unit, context),
1422                            )
1423                        }
1424                        NumberData::Subtract(a, b) => {
1425                            // Both operands are guaranteed to be unit-less here.
1426                            NumberData::Subtract(
1427                                a.clone_without_node().convert_unit(unit, context),
1428                                b.clone_without_node().convert_unit(unit, context),
1429                            )
1430                        }
1431                        NumberData::Multiply(a, b) => {
1432                            // Both operands are guaranteed to be unit-less here.
1433                            NumberData::Multiply(
1434                                a.clone_without_node().convert_unit(unit, context),
1435                                b.clone_without_node()
1436                                    .convert_unit(Some(unit::SCALAR), context),
1437                            )
1438                        }
1439                        NumberData::Divide(a, b) => {
1440                            // Both operands are guaranteed to be unit-less here.
1441                            NumberData::Divide(
1442                                a.clone_without_node().convert_unit(unit, context),
1443                                b.clone_without_node()
1444                                    .convert_unit(Some(unit::SCALAR), context),
1445                            )
1446                        }
1447                        NumberData::Average(exprs) => {
1448                            // All will be unit-less.
1449                            NumberData::Average(
1450                                exprs
1451                                    .iter()
1452                                    .map(|v| v.clone_without_node().convert_unit(unit, context))
1453                                    .collect::<Vec<_>>()
1454                                    .into(),
1455                            )
1456                        }
1457                        NumberData::Pow(base, exponent) => NumberData::Pow(
1458                            base.clone_without_node()
1459                                .convert_unit(unit.map(|x| x.pow(exponent.recip())), context),
1460                            *exponent,
1461                        ),
1462                        NumberData::Real(number) => NumberData::Real(
1463                            number.clone_without_node().convert_unit(unit, context),
1464                        ),
1465                        NumberData::Imaginary(number) => NumberData::Imaginary(
1466                            number.clone_without_node().convert_unit(unit, context),
1467                        ),
1468                    },
1469                }),
1470                ..self
1471            }
1472        }
1473    }
1474
1475    /// Checks whether a unit conversion can be performed
1476    #[must_use]
1477    pub fn can_convert_unit(&self, unit: Option<ComplexUnit>) -> bool {
1478        !(unit.is_none() || self.data.unit.is_some() && self.data.unit != unit)
1479    }
1480
1481    /// Make the unit concrete. If the unit is a `None`, will make it
1482    /// a unitless scalar. Otherwise will do nothing.
1483    ///
1484    /// # Panics
1485    /// If bugged
1486    #[must_use]
1487    pub fn specify_unit(self, context: &CompileContext) -> Self {
1488        if self.data.unit.is_none() {
1489            self.convert_unit(Some(unit::SCALAR), context)
1490        } else {
1491            self
1492        }
1493    }
1494}
1495
1496impl GetValueType for Number {
1497    fn get_value_type(&self) -> Type {
1498        Type::Number(self.unit)
1499    }
1500}
1501
1502impl Display for Number {
1503    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1504        write!(f, "{}", self.data)
1505    }
1506}
1507
1508/// Unrolled point collection expression data.
1509#[derive(Debug, CloneWithNode)]
1510pub enum PointCollectionData {
1511    /// A generic expression
1512    Generic(Generic<PointCollection>),
1513    /// A point collection in the form of a list of points.
1514    PointCollection(ClonedVec<Expr<Point>>),
1515}
1516
1517impl PointCollectionData {
1518    #[must_use]
1519    pub fn as_collection(&self) -> Option<&ClonedVec<Expr<Point>>> {
1520        match self {
1521            PointCollectionData::PointCollection(v) => Some(v),
1522            PointCollectionData::Generic(_) => None,
1523        }
1524    }
1525
1526    #[must_use]
1527    pub fn as_collection_mut(&mut self) -> Option<&mut ClonedVec<Expr<Point>>> {
1528        match self {
1529            PointCollectionData::PointCollection(v) => Some(v),
1530            PointCollectionData::Generic(_) => None,
1531        }
1532    }
1533
1534    /// Get the point at the given index.
1535    ///
1536    /// # Panics
1537    /// If the collection isn't long enough
1538    #[must_use]
1539    pub fn index(&self, index: usize) -> Expr<Point> {
1540        match self {
1541            PointCollectionData::Generic(generic) => match generic {
1542                Generic::VariableAccess(var) => var.definition.index_without_node(index),
1543                Generic::Boxed(expr) => expr.index_without_node(index),
1544                Generic::Dummy => Expr::new_spanless(Point::Generic(Generic::Dummy)),
1545            },
1546            PointCollectionData::PointCollection(col) => col.get(index).map_or_else(
1547                || Expr::new_spanless(Point::dummy()),
1548                CloneWithNode::clone_without_node,
1549            ),
1550        }
1551    }
1552}
1553
1554impl Display for PointCollectionData {
1555    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1556        match self {
1557            Self::Generic(v) => write!(f, "{v}"),
1558            Self::PointCollection(col) => write!(
1559                f,
1560                "col({})",
1561                col.iter()
1562                    .map(|v| format!("{v}"))
1563                    .collect::<Vec<String>>()
1564                    .join(", ")
1565            ),
1566        }
1567    }
1568}
1569
1570/// An unrolled point collection with size information.
1571#[derive(Debug, CloneWithNode)]
1572pub struct PointCollection {
1573    /// How many points this point collection has
1574    pub length: usize,
1575    /// The defining data.
1576    pub data: PointCollectionData,
1577}
1578
1579impl_from_any! {PointCollection}
1580impl_from_unknown! {PointCollection}
1581
1582impl_convert_err! {Circle -> PointCollection}
1583impl_convert_err! {Line -> PointCollection}
1584impl_convert_err! {Number -> PointCollection}
1585impl_convert_err! {Derived -> PointCollection}
1586
1587impl_make_variable! {PointCollection {other: length, data: PointCollectionData}}
1588
1589impl Displayed for PointCollection {
1590    type Node = PCNode;
1591}
1592
1593impl Dummy for PointCollection {
1594    fn dummy() -> Self {
1595        Self {
1596            length: 0,
1597            data: PointCollectionData::Generic(Generic::Dummy),
1598        }
1599    }
1600
1601    fn is_dummy(&self) -> bool {
1602        matches!(self.data, PointCollectionData::Generic(Generic::Dummy))
1603    }
1604}
1605
1606impl GetData for PointCollection {
1607    fn get_data(&self) -> &Self {
1608        match &self.data {
1609            PointCollectionData::Generic(v) => match v {
1610                Generic::Boxed(v) => v.get_data(),
1611                Generic::VariableAccess(v) => v.definition.get_data(),
1612                Generic::Dummy => self,
1613            },
1614            PointCollectionData::PointCollection(_) => self,
1615        }
1616    }
1617}
1618
1619impl ConvertFrom<Expr<Point>> for PointCollection {
1620    fn convert_from(mut value: Expr<Point>, _context: &CompileContext) -> Expr<Self> {
1621        let value_node = value.take_node();
1622        let mut expr = Expr {
1623            span: value.span,
1624            data: Rc::new(PointCollection {
1625                length: 1,
1626                data: PointCollectionData::PointCollection(vec![value].into()),
1627            }),
1628            node: None,
1629        };
1630        let mut node = PCNode::new(expr.clone_without_node());
1631        node.push(value_node);
1632        expr.node = Some(HierarchyNode::new(node));
1633
1634        expr
1635    }
1636
1637    fn can_convert_from(_value: &Expr<Point>) -> bool {
1638        true
1639    }
1640}
1641
1642impl ConvertFrom<Expr<PointCollection>> for PointCollection {
1643    fn convert_from(mut value: Expr<PointCollection>, context: &CompileContext) -> Expr<Self> {
1644        if let Some(node) = &mut value.node {
1645            if let Some(props) = node.root.props.take() {
1646                props.finish(context);
1647            }
1648        }
1649
1650        value
1651    }
1652
1653    fn can_convert_from(_value: &Expr<PointCollection>) -> bool {
1654        true
1655    }
1656}
1657
1658impl PointCollection {
1659    /// An associated type getter doesn't know the collection length
1660    /// so it returns a generic length of 0.
1661    #[must_use]
1662    pub fn get_type() -> Type {
1663        ty::collection(0)
1664    }
1665}
1666
1667impl Expr<PointCollection> {
1668    /// Box the expression with the given span.
1669    #[must_use]
1670    pub fn boxed(mut self, span: Span) -> Self {
1671        let node = self.node.take();
1672
1673        Self {
1674            span,
1675            data: Rc::new(PointCollection {
1676                length: self.data.length,
1677                data: PointCollectionData::Generic(Generic::Boxed(self)),
1678            }),
1679            node,
1680        }
1681    }
1682
1683    /// Check if the collection's length matches the given length.
1684    /// If `length` is zero, any length is found matching.
1685    ///
1686    /// # Errors
1687    /// Returns an error if lengths don't match up.
1688    #[must_use]
1689    pub fn check_len(self, length: usize, context: &CompileContext) -> Self {
1690        if self.data.length == length
1691            || length == 0
1692            || matches!(self.data.data, PointCollectionData::Generic(Generic::Dummy))
1693        {
1694            self
1695        } else {
1696            context.push_error(Error::ImplicitConversionDoesNotExist {
1697                error_span: self.span,
1698                from: self.get_value_type(),
1699                to: ty::collection(length),
1700            });
1701
1702            Self {
1703                data: Rc::new(PointCollection::dummy()),
1704                ..self
1705            }
1706        }
1707    }
1708
1709    /// Get the point at a given index without taking the collection's node.
1710    #[must_use]
1711    pub fn index_without_node(&self, index: usize) -> Expr<Point> {
1712        self.data.data.index(index)
1713    }
1714
1715    /// Get the point at a given index and take the collection's node.
1716    #[must_use]
1717    pub fn index_with_node(&mut self, index: usize) -> Expr<Point> {
1718        let mut point = self.data.data.index(index);
1719        point.node = self
1720            .node
1721            .as_mut()
1722            .and_then(|x| x.root.children[index].take());
1723
1724        point
1725    }
1726}
1727
1728impl GetValueType for PointCollection {
1729    fn get_value_type(&self) -> Type {
1730        ty::collection(self.length)
1731    }
1732}
1733
1734impl Display for PointCollection {
1735    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1736        write!(f, "{}", self.data)
1737    }
1738}
1739
1740/// An unrolled derived type expression data
1741#[derive(Debug, CloneWithNode)]
1742pub enum DerivedData {
1743    /// A generic expression
1744    Generic(Generic<Derived>),
1745    /// Data of this type.
1746    Data(Rc<dyn DerivedType>),
1747}
1748
1749impl Display for DerivedData {
1750    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1751        match self {
1752            Self::Generic(v) => write!(f, "{v}"),
1753            Self::Data(v) => write!(f, "{v}"),
1754        }
1755    }
1756}
1757
1758/// Trait for derived types - a special kind in GeoScript.
1759pub trait DerivedType: Debug + Display + 'static {
1760    /// Cast this into an `Any` trait object
1761    fn as_any(&self) -> &dyn Any;
1762}
1763
1764/// A special derived type expression. Used to encapsulate
1765/// special behavior behind dynamic dispatch.
1766#[derive(Debug, CloneWithNode)]
1767pub struct Derived {
1768    /// Name of this derived type.
1769    pub name: &'static str,
1770    /// The actual data.
1771    pub data: DerivedData,
1772}
1773
1774impl_x_from_x! {Derived}
1775impl_from_any! {Derived}
1776impl_from_unknown! {Derived}
1777
1778impl_convert_err! {Point -> Derived}
1779impl_convert_err! {Line -> Derived}
1780impl_convert_err! {Circle -> Derived}
1781impl_convert_err! {Number -> Derived}
1782impl_convert_err! {PointCollection -> Derived}
1783
1784impl_make_variable! {Derived {other: name, data: DerivedData}}
1785
1786impl Derived {
1787    /// Associated type getter doesn't know the specific name, so always returns `"{}"`
1788    #[must_use]
1789    pub fn get_type() -> Type {
1790        ty::derived("{}")
1791    }
1792}
1793
1794impl Displayed for Derived {
1795    type Node = dyn Node;
1796}
1797
1798impl Dummy for Derived {
1799    fn dummy() -> Self {
1800        Self {
1801            name: "dummy",
1802            data: DerivedData::Generic(Generic::Dummy),
1803        }
1804    }
1805
1806    fn is_dummy(&self) -> bool {
1807        matches!(self.data, DerivedData::Generic(Generic::Dummy))
1808    }
1809}
1810
1811impl Expr<Derived> {
1812    /// Box the expression with the given span.
1813    #[must_use]
1814    pub fn boxed(mut self, span: Span) -> Self {
1815        let node = self.node.take();
1816
1817        Self {
1818            span,
1819            data: Rc::new(Derived {
1820                name: self.data.name,
1821                data: DerivedData::Generic(Generic::Boxed(self)),
1822            }),
1823            node,
1824        }
1825    }
1826
1827    /// Check if the type's name matches the given name.
1828    ///
1829    /// # Errors
1830    /// Returns an error if the type names don't match
1831    #[must_use]
1832    pub fn check_name(self, name: &'static str, context: &CompileContext) -> Self {
1833        if self.data.name == name || matches!(self.data.data, DerivedData::Generic(Generic::Dummy))
1834        {
1835            self
1836        } else {
1837            context.push_error(Error::ImplicitConversionDoesNotExist {
1838                error_span: self.span,
1839                from: self.get_value_type(),
1840                to: ty::derived(name),
1841            });
1842
1843            Self {
1844                data: Rc::new(Derived::dummy()),
1845                ..self
1846            }
1847        }
1848    }
1849}
1850
1851impl GetData for Derived {
1852    fn get_data(&self) -> &Self {
1853        match &self.data {
1854            DerivedData::Generic(v) => match v {
1855                Generic::VariableAccess(var) => var.definition.get_data(),
1856                Generic::Boxed(v) => v.get_data(),
1857                Generic::Dummy => self,
1858            },
1859            _ => self,
1860        }
1861    }
1862}
1863
1864impl GetValueType for Derived {
1865    fn get_value_type(&self) -> Type {
1866        ty::derived(self.name)
1867    }
1868}
1869
1870impl Display for Derived {
1871    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1872        write!(f, "{} {}", self.name, self.data)
1873    }
1874}
1875
1876/// A special unknown type used for pushing unrolling as far as possible.
1877#[derive(Debug, CloneWithNode)]
1878pub enum Unknown {
1879    /// Can only be a generic expression.
1880    Generic(Generic<Unknown>),
1881}
1882
1883impl_make_variable! {Unknown}
1884
1885impl Dummy for Unknown {
1886    fn dummy() -> Self {
1887        Self::Generic(Generic::Dummy)
1888    }
1889
1890    fn is_dummy(&self) -> bool {
1891        true
1892    }
1893}
1894
1895impl Display for Unknown {
1896    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1897        match self {
1898            Self::Generic(v) => write!(f, "{v}"),
1899        }
1900    }
1901}
1902
1903impl Displayed for Unknown {
1904    type Node = EmptyNode;
1905}
1906
1907impl GetValueType for Unknown {
1908    fn get_value_type(&self) -> Type {
1909        Type::Unknown
1910    }
1911}
1912
1913impl Expr<Unknown> {
1914    /// Box the expression with the given span.
1915    #[must_use]
1916    pub fn boxed(mut self, span: Span) -> Self {
1917        let node = self.take_node();
1918
1919        Self {
1920            data: Rc::new(Unknown::Generic(Generic::Boxed(self))),
1921            span,
1922            node,
1923        }
1924    }
1925}
1926
1927/// A type-erased unrolled expression.
1928#[derive(Debug, CloneWithNode)]
1929pub enum AnyExpr {
1930    Point(Expr<Point>),
1931    Line(Expr<Line>),
1932    Number(Expr<Number>),
1933    Circle(Expr<Circle>),
1934    PointCollection(Expr<PointCollection>),
1935    Derived(Expr<Derived>),
1936    Unknown(Expr<Unknown>),
1937}
1938
1939impl_any_from_x! {Point}
1940impl_any_from_x! {Line}
1941impl_any_from_x! {Number}
1942impl_any_from_x! {Circle}
1943impl_any_from_x! {PointCollection}
1944impl_any_from_x! {Derived}
1945impl_any_from_x! {Unknown}
1946
1947impl AnyExpr {
1948    /// Clones the expression and sets its own span. This will be treated as a separate expression now.
1949    #[must_use]
1950    pub fn get_span_mut(&mut self) -> &mut Span {
1951        match self {
1952            Self::Point(v) => &mut v.span,
1953            Self::Line(v) => &mut v.span,
1954            Self::Number(v) => &mut v.span,
1955            Self::Circle(v) => &mut v.span,
1956            Self::PointCollection(v) => &mut v.span,
1957            Self::Derived(v) => &mut v.span,
1958            Self::Unknown(v) => &mut v.span,
1959        }
1960    }
1961
1962    /// Get the expression's span.
1963    #[must_use]
1964    pub fn get_span(&self) -> Span {
1965        match self {
1966            Self::Point(v) => v.span,
1967            Self::Line(v) => v.span,
1968            Self::Number(v) => v.span,
1969            Self::Circle(v) => v.span,
1970            Self::PointCollection(v) => v.span,
1971            Self::Derived(v) => v.span,
1972            Self::Unknown(v) => v.span,
1973        }
1974    }
1975
1976    /// Replace the display node with the given node. Also returns the old node.
1977    pub fn replace_node(&mut self, with: Option<AnyExprNode>) -> Option<AnyExprNode> {
1978        Some(match self {
1979            Self::Point(v) => {
1980                AnyExprNode::Point(mem::replace(&mut v.node, with.map(AnyExprNode::to_point))?)
1981            }
1982            Self::Line(v) => {
1983                AnyExprNode::Line(mem::replace(&mut v.node, with.map(AnyExprNode::to_line))?)
1984            }
1985            Self::Number(v) => {
1986                AnyExprNode::Number(mem::replace(&mut v.node, with.map(AnyExprNode::to_scalar))?)
1987            }
1988            Self::Circle(v) => {
1989                AnyExprNode::Circle(mem::replace(&mut v.node, with.map(AnyExprNode::to_circle))?)
1990            }
1991            Self::PointCollection(v) => AnyExprNode::PointCollection(mem::replace(
1992                &mut v.node,
1993                with.map(AnyExprNode::to_point_collection),
1994            )?),
1995            Self::Derived(v) => AnyExprNode::Derived(mem::replace(
1996                &mut v.node,
1997                with.map(AnyExprNode::to_derived),
1998            )?),
1999            Self::Unknown(v) => AnyExprNode::Unknown(mem::replace(
2000                &mut v.node,
2001                with.map(AnyExprNode::to_unknown),
2002            )?),
2003        })
2004    }
2005
2006    /// Get the node without taking it (reference).
2007    #[must_use]
2008    pub fn get_node(&self) -> Option<&dyn Node> {
2009        match self {
2010            Self::Point(x) => x.node.as_ref().map(|c| c as &dyn Node),
2011            Self::Line(x) => x.node.as_ref().map(|c| c as &dyn Node),
2012            Self::Number(x) => x.node.as_ref().map(|c| c as &dyn Node),
2013            Self::Circle(x) => x.node.as_ref().map(|c| c as &dyn Node),
2014            Self::PointCollection(x) => x.node.as_ref().map(|c| c as &dyn Node),
2015            Self::Derived(x) => x.node.as_ref().map(|c| c as &dyn Node),
2016            Self::Unknown(x) => x.node.as_ref().map(|c| c as &dyn Node),
2017        }
2018    }
2019
2020    #[must_use]
2021    pub fn to_scalar(self) -> Option<Expr<Number>> {
2022        match self {
2023            Self::Number(v) => Some(v),
2024            _ => None,
2025        }
2026    }
2027
2028    #[must_use]
2029    pub fn as_point(&self) -> Option<&Expr<Point>> {
2030        match self {
2031            Self::Point(v) => Some(v),
2032            _ => None,
2033        }
2034    }
2035
2036    /// Get the expression's value type.
2037    #[must_use]
2038    pub fn get_type(&self) -> Type {
2039        match self {
2040            AnyExpr::Point(v) => v.get_value_type(),
2041            AnyExpr::Line(v) => v.get_value_type(),
2042            AnyExpr::Number(v) => v.get_value_type(),
2043            AnyExpr::Circle(v) => v.get_value_type(),
2044            AnyExpr::PointCollection(v) => v.get_value_type(),
2045            AnyExpr::Derived(v) => v.get_value_type(),
2046            AnyExpr::Unknown(v) => v.get_value_type(),
2047        }
2048    }
2049
2050    /// Convert this expression to the given type.
2051    ///
2052    /// # Errors
2053    /// Returns an error if the conversion is invalid.
2054    #[must_use]
2055    pub fn convert_to(self, to: Type, context: &CompileContext) -> Self {
2056        match to {
2057            Type::Point => Self::Point(self.convert(context)),
2058            Type::Line => Self::Line(self.convert(context)),
2059            Type::Number(unit) => Self::Number(self.convert(context).convert_unit(unit, context)),
2060            Type::PointCollection(len) => {
2061                Self::PointCollection(self.convert(context).check_len(len, context))
2062            }
2063            Type::Circle => Self::Circle(self.convert(context)),
2064            Type::Derived(name) => Self::Derived(self.convert(context).check_name(name, context)),
2065            Type::Unknown => Self::Unknown(Expr::dummy()),
2066        }
2067    }
2068
2069    /// Check if this expression is convertible to the given type.
2070    #[must_use]
2071    pub fn can_convert_to(&self, to: Type) -> bool {
2072        match to {
2073            Type::Point => self.can_convert::<Point>(),
2074            Type::Line => self.can_convert::<Line>(),
2075            Type::Number(unit) => self.can_convert_to_scalar(unit).is_some(),
2076            Type::PointCollection(len) => self.can_convert_to_collection(len).is_some(),
2077            Type::Circle => self.can_convert::<Circle>(),
2078            Type::Derived(name) => self.can_convert_to_derived(name),
2079            Type::Unknown => true,
2080        }
2081    }
2082
2083    /// Check if the expression is convertible to the given type.
2084    /// Note that `unit` of `None` is ANY scalar, not UNKNOWN-UNIT scalar here.
2085    /// Returns `None` if conversion isn't possible and `Some` with a unit
2086    /// this value would be converted to. If `unit` is `None` and the value
2087    /// is also an unknown-unit scalar, `Some(None)` is returned.
2088    #[must_use]
2089    pub fn can_convert_to_scalar(&self, unit: Option<ComplexUnit>) -> Option<Option<ComplexUnit>> {
2090        match self {
2091            Self::Line(_) | Self::Derived(_) | Self::Circle(_) | Self::Point(_) => None,
2092            Self::PointCollection(v) => (v.data.length == 2
2093                && (unit == Some(unit::DISTANCE) || unit.is_none()))
2094            .then_some(Some(unit::DISTANCE)),
2095            Self::Number(u) => (u.data.unit == unit || u.data.unit.is_none() || unit.is_none())
2096                .then_some(u.data.unit.or(unit)),
2097            Self::Unknown(_) => Some(unit),
2098        }
2099    }
2100
2101    /// Check if the expression is convertible to a point collection of the given length.
2102    #[must_use]
2103    pub fn can_convert_to_collection(&self, len: usize) -> Option<usize> {
2104        match self {
2105            Self::Line(_) | Self::Derived(_) | Self::Circle(_) | Self::Number(_) => None,
2106            Self::PointCollection(v) => (v.data.length == len || len == 0).then_some(v.data.length),
2107            Self::Point(_) => (len == 1 || len == 0).then_some(1),
2108            Self::Unknown(_) => Some(0),
2109        }
2110    }
2111
2112    /// Check if the expression is convertible to a derived type with the given name.
2113    #[must_use]
2114    pub fn can_convert_to_derived(&self, name: &str) -> bool {
2115        match self {
2116            Self::Derived(derived) => derived.data.name == name,
2117            Self::Unknown(_) => true,
2118            _ => false,
2119        }
2120    }
2121
2122    /// Box an expression with the given span.
2123    #[must_use]
2124    pub fn boxed(self, span: Span) -> Self {
2125        match self {
2126            Self::Point(v) => Self::Point(v.boxed(span)),
2127            Self::Line(v) => Self::Line(v.boxed(span)),
2128            Self::Number(v) => Self::Number(v.boxed(span)),
2129            Self::Circle(v) => Self::Circle(v.boxed(span)),
2130            Self::PointCollection(v) => Self::PointCollection(v.boxed(span)),
2131            Self::Derived(v) => Self::Derived(v.boxed(span)),
2132            Self::Unknown(v) => Self::Unknown(v.boxed(span)),
2133        }
2134    }
2135
2136    /// Get the underlying variable's defining span.
2137    ///
2138    /// # Panics
2139    /// Panics if not a variable.
2140    #[must_use]
2141    pub fn get_variable_span(&self) -> Span {
2142        match self {
2143            Self::Point(v) => match v.data.as_ref() {
2144                Point::Generic(Generic::VariableAccess(var)) => var.definition_span,
2145                _ => panic!("not a variable"),
2146            },
2147            Self::Line(v) => match v.data.as_ref() {
2148                Line::Generic(Generic::VariableAccess(var)) => var.definition_span,
2149                _ => panic!("not a variable"),
2150            },
2151            Self::Number(v) => match &v.data.data {
2152                NumberData::Generic(Generic::VariableAccess(var)) => var.definition_span,
2153                _ => panic!("not a variable"),
2154            },
2155            Self::Circle(v) => match v.data.as_ref() {
2156                Circle::Generic(Generic::VariableAccess(var)) => var.definition_span,
2157                _ => panic!("not a variable"),
2158            },
2159            Self::PointCollection(v) => match &v.data.data {
2160                PointCollectionData::Generic(Generic::VariableAccess(var)) => var.definition_span,
2161                _ => panic!("not a variable"),
2162            },
2163            Self::Derived(v) => match &v.data.data {
2164                DerivedData::Generic(Generic::VariableAccess(var)) => var.definition_span,
2165                _ => panic!("not a variable"),
2166            },
2167            Self::Unknown(v) => match v.data.as_ref() {
2168                Unknown::Generic(Generic::VariableAccess(var)) => var.definition_span,
2169                Unknown::Generic(_) => panic!("not a variable"),
2170            },
2171        }
2172    }
2173
2174    /// Turn this expression into a variable with the given name.
2175    #[must_use]
2176    pub fn make_variable(self, name: String) -> Self {
2177        match self {
2178            Self::Point(v) => Self::Point(v.make_variable(name)),
2179            Self::Line(v) => Self::Line(v.make_variable(name)),
2180            Self::Number(v) => Self::Number(v.make_variable(name)),
2181            Self::Circle(v) => Self::Circle(v.make_variable(name)),
2182            Self::PointCollection(v) => Self::PointCollection(v.make_variable(name)),
2183            Self::Derived(v) => Self::Derived(v.make_variable(name)),
2184            Self::Unknown(v) => Self::Unknown(v.make_variable(name)),
2185        }
2186    }
2187
2188    #[must_use]
2189    pub fn as_derived(&self) -> Option<&Expr<Derived>> {
2190        if let Self::Derived(v) = self {
2191            Some(v)
2192        } else {
2193            None
2194        }
2195    }
2196
2197    pub fn try_into_derived(self) -> Result<Expr<Derived>, Self> {
2198        if let Self::Derived(v) = self {
2199            Ok(v)
2200        } else {
2201            Err(self)
2202        }
2203    }
2204
2205    #[must_use]
2206    pub fn as_number(&self) -> Option<&Expr<Number>> {
2207        if let Self::Number(v) = self {
2208            Some(v)
2209        } else {
2210            None
2211        }
2212    }
2213}
2214
2215impl Dummy for AnyExpr {
2216    fn dummy() -> Self {
2217        Self::Unknown(Expr::dummy())
2218    }
2219
2220    fn is_dummy(&self) -> bool {
2221        match self {
2222            Self::Point(v) => v.is_dummy(),
2223            Self::Line(v) => v.is_dummy(),
2224            Self::Number(v) => v.is_dummy(),
2225            Self::Circle(v) => v.is_dummy(),
2226            Self::PointCollection(v) => v.is_dummy(),
2227            Self::Derived(v) => v.is_dummy(),
2228            Self::Unknown(v) => v.is_dummy(),
2229        }
2230    }
2231}
2232
2233impl Display for AnyExpr {
2234    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2235        match self {
2236            Self::Point(v) => write!(f, "{v}"),
2237            Self::Line(v) => write!(f, "{v}"),
2238            Self::Number(v) => write!(f, "{v}"),
2239            Self::Circle(v) => write!(f, "{v}"),
2240            Self::PointCollection(v) => write!(f, "{v}"),
2241            Self::Derived(v) => write!(f, "{v}"),
2242            Self::Unknown(v) => write!(f, "{v}"),
2243        }
2244    }
2245}
2246
2247/// Helper function for displaying vectors.
2248pub fn display_vec<T: Display>(v: &[T]) -> String {
2249    v.iter()
2250        .map(|x| format!("{x}"))
2251        .collect::<Vec<String>>()
2252        .join(", ")
2253}
2254
2255/// A helper trait with functions for dummy values that pretend to be valid.
2256pub trait Dummy {
2257    /// Create a dummy value pretending to be a valid one.
2258    #[must_use]
2259    fn dummy() -> Self;
2260
2261    /// Check if this is a dummy value.
2262    #[must_use]
2263    fn is_dummy(&self) -> bool;
2264}
2265
2266/// A trait with a single associated type. Used with expressions that can be displayed.
2267pub trait Displayed: Sized {
2268    /// The display node type to use for displaying `Self`
2269    type Node: Node + ?Sized;
2270}
2271
2272/// Get the underlying data with no indirections.
2273pub trait GetData {
2274    /// Get the underlying data with no indirections.
2275    #[must_use]
2276    fn get_data(&self) -> &Self;
2277}
2278
2279/// Used for distinction between cloning an expression AND taking its node
2280/// and cloning an expression WITHOUT taking its node.
2281pub trait CloneWithNode {
2282    /// Clone `self` and take its node.
2283    #[must_use]
2284    fn clone_with_node(&mut self) -> Self;
2285
2286    /// Clone `self` without taking its node.
2287    #[must_use]
2288    fn clone_without_node(&self) -> Self;
2289}
2290
2291/// Wrapper struct for a cloned vec for use with the [`CloneWithNode`]
2292#[derive(Debug)]
2293pub struct ClonedVec<T>(pub Vec<T>);
2294
2295impl<T> From<Vec<T>> for ClonedVec<T> {
2296    fn from(value: Vec<T>) -> Self {
2297        Self(value)
2298    }
2299}
2300
2301impl<T> Deref for ClonedVec<T> {
2302    type Target = Vec<T>;
2303
2304    fn deref(&self) -> &Self::Target {
2305        &self.0
2306    }
2307}
2308
2309impl<T> DerefMut for ClonedVec<T> {
2310    fn deref_mut(&mut self) -> &mut Self::Target {
2311        &mut self.0
2312    }
2313}
2314
2315/// Wrapper struct for a cloned map used with the [`CloneWithNode`] trait.
2316#[derive(Debug)]
2317pub struct ClonedMap<K, V>(pub HashMap<K, V>);
2318
2319impl<K, V> From<HashMap<K, V>> for ClonedMap<K, V> {
2320    fn from(value: HashMap<K, V>) -> Self {
2321        Self(value)
2322    }
2323}
2324
2325impl<K, V> Deref for ClonedMap<K, V> {
2326    type Target = HashMap<K, V>;
2327
2328    fn deref(&self) -> &Self::Target {
2329        &self.0
2330    }
2331}
2332
2333impl<K, V> DerefMut for ClonedMap<K, V> {
2334    fn deref_mut(&mut self) -> &mut Self::Target {
2335        &mut self.0
2336    }
2337}
2338
2339impl<T: Clone> CloneWithNode for T {
2340    fn clone_with_node(&mut self) -> Self {
2341        self.clone()
2342    }
2343
2344    fn clone_without_node(&self) -> Self {
2345        self.clone()
2346    }
2347}
2348
2349impl<T: CloneWithNode> CloneWithNode for ClonedVec<T> {
2350    fn clone_with_node(&mut self) -> Self {
2351        self.iter_mut()
2352            .map(CloneWithNode::clone_with_node)
2353            .collect::<Vec<_>>()
2354            .into()
2355    }
2356
2357    fn clone_without_node(&self) -> Self {
2358        self.iter()
2359            .map(CloneWithNode::clone_without_node)
2360            .collect::<Vec<_>>()
2361            .into()
2362    }
2363}
2364
2365impl<K: Hash + CloneWithNode + Eq, V: CloneWithNode> CloneWithNode for ClonedMap<K, V> {
2366    fn clone_with_node(&mut self) -> Self {
2367        self.iter_mut()
2368            .map(|(k, v)| (k.clone_without_node(), v.clone_with_node()))
2369            .collect::<HashMap<_, _>>()
2370            .into()
2371    }
2372
2373    fn clone_without_node(&self) -> Self {
2374        self.iter()
2375            .map(|(k, v)| (k.clone_without_node(), v.clone_without_node()))
2376            .collect::<HashMap<_, _>>()
2377            .into()
2378    }
2379}
2380
2381/// An unrolled expression with a span and a display node.
2382#[derive(Debug)]
2383pub struct Expr<T: Displayed> {
2384    /// The expression kind.
2385    pub data: Rc<T>,
2386    /// The expression's span.
2387    pub span: Span,
2388    /// The expression's display node, if any.
2389    pub node: Option<HierarchyNode<T::Node>>,
2390}
2391
2392impl<T: GetData + Displayed> Expr<T> {
2393    /// Get the underlying data without any indirections.
2394    #[must_use]
2395    pub fn get_data(&self) -> &T {
2396        self.data.get_data()
2397    }
2398}
2399
2400impl<T: Displayed> CloneWithNode for Expr<T> {
2401    fn clone_with_node(&mut self) -> Self {
2402        Self {
2403            data: Rc::clone(&self.data),
2404            span: self.span,
2405            node: self.node.take(),
2406        }
2407    }
2408
2409    fn clone_without_node(&self) -> Self {
2410        Self {
2411            data: Rc::clone(&self.data),
2412            span: self.span,
2413            node: None,
2414        }
2415    }
2416}
2417
2418impl<T: GetValueType + Displayed> GetValueType for Expr<T> {
2419    fn get_value_type(&self) -> Type {
2420        self.data.get_value_type()
2421    }
2422}
2423
2424impl<T: Display + Displayed> Display for Expr<T> {
2425    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2426        write!(f, "{}", self.data)
2427    }
2428}
2429
2430impl<T: Displayed> Expr<T> {
2431    /// Creates a new expression without a declared span. WARNING: the expression has no node.
2432    #[must_use]
2433    pub fn new_spanless(data: T) -> Self {
2434        Self {
2435            span: span!(0, 0, 0, 0),
2436            data: Rc::new(data),
2437            node: None,
2438        }
2439    }
2440
2441    /// Take the expression's display node.
2442    pub fn take_node(&mut self) -> Option<HierarchyNode<T::Node>> {
2443        self.node.take()
2444    }
2445}
2446
2447impl<T: Displayed + Dummy> Dummy for Expr<T> {
2448    fn dummy() -> Self {
2449        Self::new_spanless(T::dummy())
2450    }
2451
2452    fn is_dummy(&self) -> bool {
2453        self.data.is_dummy()
2454    }
2455}
2456
2457/// An unrolled rule with a kind and additional data.
2458#[derive(Debug)]
2459pub struct UnrolledRule {
2460    /// The kind of this rule
2461    pub kind: UnrolledRuleKind,
2462    /// Whether the rule is inverted
2463    pub inverted: bool,
2464    /// The rule's weight
2465    pub weight: ProcNum,
2466}
2467
2468impl Display for UnrolledRule {
2469    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2470        let inv = if self.inverted { "!" } else { "" };
2471
2472        match &self.kind {
2473            UnrolledRuleKind::PointEq(a, b) => write!(f, "{a} {inv}= {b}"),
2474            UnrolledRuleKind::NumberEq(a, b) => write!(f, "{a} {inv}= {b}"),
2475            UnrolledRuleKind::Gt(a, b) => {
2476                write!(f, "{a} {} {b}", if self.inverted { "<=" } else { ">" })
2477            }
2478            UnrolledRuleKind::Alternative(v) => {
2479                write!(
2480                    f,
2481                    "{}",
2482                    v.iter()
2483                        .map(|x| format!("{x}"))
2484                        .collect::<Vec<String>>()
2485                        .join(" || ")
2486                )
2487            }
2488            UnrolledRuleKind::Bias(v) => write!(f, "bias {v}"),
2489        }
2490    }
2491}
2492
2493// /// A point id is a 64-bit integer. First 32 bits are for the letter codepoint, next 8 for the amount of primes, next 16 for the point index.
2494// fn construct_point_id(letter: char, primes: u8) -> u64 {
2495//     ((letter as u64) << 8) | u64::from(primes)
2496// }
2497
2498/// Constructs the point name based on the letter and the primes.
2499#[must_use]
2500pub fn construct_point_name(letter: char, primes: u8) -> String {
2501    String::from(letter) + &"'".repeat(primes as usize)
2502}
2503
2504/// Fetch the variable's defining expression by its name.
2505fn fetch_variable(context: &CompileContext, name: &str, variable_span: Span) -> AnyExpr {
2506    let mut var = if let Some(var) = context.variables.get(name) {
2507        var.clone_without_node()
2508    } else {
2509        let suggested = most_similar(context.variables.keys(), name);
2510
2511        context.push_error(Error::UndefinedVariable {
2512            error_span: variable_span,
2513            variable_name: name.to_string(),
2514            suggested: suggested.cloned(),
2515            suggest_complex: name == "i",
2516        });
2517
2518        Expr::new_spanless(Unknown::dummy())
2519            .make_variable(name.to_string())
2520            .into()
2521    };
2522
2523    *var.get_span_mut() = variable_span;
2524    var
2525}
2526
2527impl Unroll for SimpleExpression {
2528    fn unroll(
2529        &self,
2530        context: &mut CompileContext,
2531        library: &Library,
2532        it_index: &HashMap<u8, usize>,
2533        display: Properties,
2534    ) -> AnyExpr {
2535        let display = Properties::from(self.display.clone()).merge_with(display);
2536
2537        let unrolled = self.kind.unroll(context, library, it_index, display);
2538        let unrolled = if let Some(exponent) = &self.exponent {
2539            let mut unrolled: Expr<Number> = unrolled.convert(context);
2540            let node = unrolled.node.take();
2541
2542            let exponent = match exponent.exponent.as_comp() {
2543                Ok(v) => {
2544                    if self.minus.is_some() {
2545                        -v
2546                    } else {
2547                        v
2548                    }
2549                }
2550                Err(err) => {
2551                    context.push_error(err);
2552                    CompExponent::one()
2553                }
2554            };
2555
2556            AnyExpr::Number(Expr {
2557                span: self.get_span(),
2558                data: Rc::new(Number {
2559                    unit: unrolled.data.unit.map(|v| v.pow(exponent)),
2560                    data: NumberData::Pow(unrolled, exponent),
2561                }),
2562                node,
2563            })
2564        } else {
2565            unrolled
2566        };
2567
2568        if self.minus.is_some() {
2569            let mut unrolled: Expr<Number> = unrolled.convert(context);
2570            let node = unrolled.node.take();
2571
2572            AnyExpr::Number(Expr {
2573                span: self.get_span(),
2574                data: Rc::new(Number {
2575                    unit: unrolled.data.unit,
2576                    data: NumberData::Negate(unrolled),
2577                }),
2578                node,
2579            })
2580        } else {
2581            unrolled
2582        }
2583    }
2584}
2585
2586/// A function reference: either a named one or a method.
2587#[derive(Debug)]
2588pub enum FuncRef {
2589    Function(String),
2590    /// Method with the given name on the given value.
2591    Method(String, AnyExpr),
2592    /// An invalid function reference
2593    Invalid,
2594}
2595
2596impl Unroll for Ident {
2597    fn unroll(
2598        &self,
2599        context: &mut CompileContext,
2600        _library: &Library,
2601        _it_index: &HashMap<u8, usize>,
2602        display: Properties,
2603    ) -> AnyExpr {
2604        match self {
2605            Ident::Named(named) => {
2606                // No options are expected, as var refs don't generate nodes.
2607                display.finish(context);
2608
2609                fetch_variable(context, &named.ident, named.span)
2610            }
2611            Ident::Collection(col) => {
2612                let mut display = display;
2613                let display_pc = display.get("display").maybe_unset(true);
2614
2615                let mut pc_children = Vec::new();
2616                pc_children.resize_with(col.collection.len(), || None);
2617
2618                // No options are expected, as pcs don't generate nodes.
2619                let mut expr = Expr {
2620                    data: Rc::new(PointCollection {
2621                        length: col.collection.len(),
2622                        data: PointCollectionData::PointCollection(
2623                            col.collection
2624                                .iter()
2625                                .map(|item| {
2626                                    fetch_variable(context, &format!("{item}"), col.span)
2627                                        .convert::<Point>(context)
2628                                })
2629                                .collect::<Vec<_>>()
2630                                .into(),
2631                        ),
2632                    }),
2633                    span: col.span,
2634                    node: None,
2635                };
2636                expr.node = Some(HierarchyNode::new(PCNode {
2637                    display: display_pc,
2638                    children: pc_children,
2639                    props: Some(display),
2640                    expr: expr.clone_without_node(),
2641                }));
2642                AnyExpr::PointCollection(expr)
2643            }
2644        }
2645    }
2646}
2647
2648impl Unroll for ExprCall {
2649    fn unroll(
2650        &self,
2651        context: &mut CompileContext,
2652        library: &Library,
2653        it_index: &HashMap<u8, usize>,
2654        mut display: Properties,
2655    ) -> AnyExpr {
2656        let name = self
2657            .name
2658            .unroll(context, library, it_index, Properties::default());
2659
2660        let (func_name, self_param) = match name {
2661            FuncRef::Function(x) => (x, None),
2662            FuncRef::Method(x, y) => (x, Some(y)),
2663            FuncRef::Invalid => {
2664                display.ignore_all();
2665                display.finish(context);
2666                return AnyExpr::Unknown(Expr::new_spanless(Unknown::dummy()));
2667            }
2668        };
2669
2670        let self_type = self_param.as_ref().map(AnyExpr::get_type);
2671
2672        let mut params = Vec::new();
2673        params.extend(self_param);
2674
2675        if let Some(parsed) = &self.params {
2676            for p in parsed.iter() {
2677                params.push(p.unroll(context, library, it_index, Properties::default()));
2678            }
2679        }
2680
2681        let func = match self_type {
2682            Some(t) => library.get_method(t, &func_name),
2683            None => library.get_function(&func_name),
2684        };
2685
2686        let res = match func {
2687            Ok(func) => {
2688                if let Some(overload) = func.get_overload(&params) {
2689                    let ret = overload.unroll(params, context, display);
2690
2691                    return ret.boxed(self.get_span());
2692                }
2693
2694                context.push_error(Error::OverloadNotFound {
2695                    error_span: self.get_span(),
2696                    function_name: func_name.clone(),
2697                    params: params.iter().map(AnyExpr::get_type).collect(),
2698                });
2699
2700                Expr {
2701                    data: Rc::new(Unknown::dummy()),
2702                    span: self.get_span(),
2703                    node: None,
2704                }
2705                .into()
2706            }
2707            Err(suggested) => {
2708                if let Some(self_type) = self_type {
2709                    context.push_error(Error::UndefinedMethod {
2710                        error_span: self.name.get_span(),
2711                        function_name: func_name,
2712                        on_type: self_type,
2713                        suggested,
2714                    });
2715                } else {
2716                    context.push_error(Error::UndefinedFunction {
2717                        error_span: self.name.get_span(),
2718                        function_name: func_name.clone(),
2719                        suggested,
2720                    });
2721                }
2722
2723                Expr::new_spanless(Unknown::dummy()).into()
2724            }
2725        };
2726
2727        for mut param in params {
2728            if let Some(AnyExprNode::PointCollection(mut pc)) = param.replace_node(None) {
2729                if let Some(props) = pc.root.props.take() {
2730                    props.finish(context);
2731                }
2732            }
2733        }
2734
2735        display.ignore_all();
2736        display.finish(context);
2737
2738        res
2739    }
2740}
2741
2742impl Unroll for Name {
2743    fn unroll(
2744        &self,
2745        context: &mut CompileContext,
2746        library: &Library,
2747        it_index: &HashMap<u8, usize>,
2748        display: Properties,
2749    ) -> AnyExpr {
2750        match self {
2751            Self::Ident(i) => i.unroll(context, library, it_index, display),
2752            Self::Call(expr) => expr.unroll(context, library, it_index, display),
2753            Self::Expression(v) => v.content.unroll(context, library, it_index, display),
2754            Self::FieldIndex(_) => {
2755                context.push_error(Error::FieldAccess {
2756                    error_span: self.get_span(),
2757                });
2758
2759                Expr::new_spanless(Unknown::dummy()).into()
2760            }
2761        }
2762    }
2763}
2764
2765impl Unroll<FuncRef> for Name {
2766    fn unroll(
2767        &self,
2768        context: &mut CompileContext,
2769        library: &Library,
2770        it_index: &HashMap<u8, usize>,
2771        display: Properties,
2772    ) -> FuncRef {
2773        display.finish(context);
2774
2775        match self {
2776            Self::Ident(Ident::Named(n)) => FuncRef::Function(n.ident.clone()),
2777            Self::FieldIndex(f) => {
2778                let self_param: AnyExpr =
2779                    f.name
2780                        .unroll(context, library, it_index, Properties::default());
2781                let name = match &f.field {
2782                    Ident::Named(n) => n.ident.clone(),
2783                    Ident::Collection(_) => {
2784                        context.push_error(Error::ExpectedFunction {
2785                            error_span: self.get_span(),
2786                        });
2787
2788                        return FuncRef::Invalid;
2789                    }
2790                };
2791
2792                match self_param {
2793                    AnyExpr::Unknown(_) => FuncRef::Invalid,
2794                    self_param => FuncRef::Method(name, self_param),
2795                }
2796            }
2797            _ => {
2798                context.push_error(Error::ExpectedFunction {
2799                    error_span: self.get_span(),
2800                });
2801
2802                FuncRef::Invalid
2803            }
2804        }
2805    }
2806}
2807
2808impl Unroll for NumberLit {
2809    fn unroll(
2810        &self,
2811        context: &mut CompileContext,
2812        _library: &Library,
2813        _it_index: &HashMap<u8, usize>,
2814        display: Properties,
2815    ) -> AnyExpr {
2816        display.finish(context);
2817
2818        AnyExpr::Number(Expr {
2819            data: Rc::new(Number {
2820                unit: None,
2821                data: NumberData::Number(self.into()),
2822            }),
2823            span: self.get_span(),
2824            node: None,
2825        })
2826    }
2827}
2828
2829impl Unroll for ExplicitIterator {
2830    fn unroll(
2831        &self,
2832        context: &mut CompileContext,
2833        library: &Library,
2834        it_index: &HashMap<u8, usize>,
2835        display: Properties,
2836    ) -> AnyExpr {
2837        self.get(it_index[&self.id])
2838            .unwrap()
2839            .unroll(context, library, it_index, display)
2840    }
2841}
2842
2843impl Unroll for PointCollectionConstructor {
2844    fn unroll(
2845        &self,
2846        context: &mut CompileContext,
2847        library: &Library,
2848        it_index: &HashMap<u8, usize>,
2849        mut display: Properties,
2850    ) -> AnyExpr {
2851        let display_pc = display.get("display").maybe_unset(true);
2852
2853        let mut pc_children = Vec::new();
2854        pc_children.resize_with(self.points.len(), || None);
2855
2856        let mut expr = Expr {
2857            span: self.get_span(),
2858            data: Rc::new(PointCollection {
2859                length: self.points.len(),
2860                data: PointCollectionData::PointCollection({
2861                    let mut points = Vec::new();
2862
2863                    for expr in self.points.iter() {
2864                        let mut unrolled =
2865                            expr.unroll(context, library, it_index, Properties::default());
2866
2867                        if unrolled.can_convert_to(ty::POINT) {
2868                            points.push(unrolled.convert(context));
2869                        } else {
2870                            context.push_error(Error::NonPointInPointCollection {
2871                                error_span: self.get_span(),
2872                                received: (expr.get_span(), unrolled.get_type()), // (span, from)
2873                            });
2874
2875                            // Pretend the point is valid.
2876                            points.push(Expr {
2877                                span: unrolled.get_span(),
2878                                data: Rc::new(Point::dummy()),
2879                                node: unrolled.replace_node(None).map(AnyExprNode::to_point),
2880                            });
2881                        }
2882                    }
2883
2884                    for pt in &mut points {
2885                        pc_children.push(pt.take_node());
2886                    }
2887
2888                    points.into()
2889                }),
2890            }),
2891            node: None,
2892        };
2893
2894        expr.node = Some(HierarchyNode::new(PCNode {
2895            display: display_pc,
2896            children: pc_children,
2897            props: Some(display),
2898            expr: expr.clone_without_node(),
2899        }));
2900
2901        AnyExpr::PointCollection(expr)
2902    }
2903}
2904
2905impl Unroll for SimpleExpressionKind {
2906    fn unroll(
2907        &self,
2908        context: &mut CompileContext,
2909        library: &Library,
2910        it_index: &HashMap<u8, usize>,
2911        display: Properties,
2912    ) -> AnyExpr {
2913        match self {
2914            Self::Name(name) => name.unroll(context, library, it_index, display),
2915            Self::Number(num) => num.unroll(context, library, it_index, display),
2916            Self::ExplicitIterator(it) => it.unroll(context, library, it_index, display),
2917            Self::PointCollection(col) => col.unroll(context, library, it_index, display),
2918        }
2919    }
2920}
2921
2922impl<const ITER: bool> Unroll for ExprBinop<ITER> {
2923    fn unroll(
2924        &self,
2925        context: &mut CompileContext,
2926        library: &Library,
2927        it_index: &HashMap<u8, usize>,
2928        display: Properties,
2929    ) -> AnyExpr {
2930        let lhs = self
2931            .lhs
2932            .unroll(context, library, it_index, Properties::default());
2933        let rhs = self
2934            .rhs
2935            .unroll(context, library, it_index, Properties::default());
2936
2937        let mut lhs = if lhs.can_convert_to(ty::SCALAR_UNKNOWN) {
2938            lhs.convert::<Number>(context)
2939        } else {
2940            context.push_error(Error::InvalidOperandType {
2941                error_span: Box::new(self.get_span()),
2942                got: (lhs.get_type(), Box::new(lhs.get_span())),
2943                op: self.operator.to_string(),
2944            });
2945
2946            Expr {
2947                span: lhs.get_span(),
2948                data: Rc::new(Number::dummy()),
2949                node: None,
2950            }
2951        };
2952
2953        let mut rhs = if rhs.can_convert_to(ty::SCALAR_UNKNOWN) {
2954            rhs.convert::<Number>(context)
2955        } else {
2956            context.push_error(Error::InvalidOperandType {
2957                error_span: Box::new(self.get_span()),
2958                got: (rhs.get_type(), Box::new(rhs.get_span())),
2959                op: self.operator.to_string(),
2960            });
2961
2962            Expr {
2963                span: rhs.get_span(),
2964                data: Rc::new(Number::dummy()),
2965                node: None,
2966            }
2967        };
2968
2969        // Binary operators generate collection nodes for the lhs and rhs nodes.
2970        let lhs_node = lhs.take_node();
2971        let rhs_node = rhs.take_node();
2972
2973        match &self.operator {
2974            BinaryOperator::Add(_) | BinaryOperator::Sub(_) => {
2975                let lhs = if lhs.data.unit.is_none() {
2976                    lhs.convert_unit(rhs.data.unit, context)
2977                } else {
2978                    lhs
2979                };
2980
2981                let rhs = rhs.convert_unit(lhs.data.unit, context);
2982                let mut expr = Expr {
2983                    span: self.get_span(),
2984                    data: Rc::new(Number {
2985                        unit: rhs.data.unit,
2986                        data: match &self.operator {
2987                            BinaryOperator::Add(_) => NumberData::Add(lhs, rhs),
2988                            BinaryOperator::Sub(_) => NumberData::Subtract(lhs, rhs),
2989                            _ => unreachable!(),
2990                        },
2991                    }),
2992                    node: None,
2993                };
2994
2995                let mut node = HierarchyNode::new(NumberNode::from_expr(&expr, display, context));
2996                node.extend_children(lhs_node);
2997                node.extend_children(rhs_node);
2998
2999                expr.node = Some(node);
3000
3001                AnyExpr::Number(expr)
3002            }
3003            BinaryOperator::Mul(_) | BinaryOperator::Div(_) => {
3004                let lhs = lhs.specify_unit(context);
3005
3006                let rhs = rhs.specify_unit(context);
3007                let mut expr = Expr {
3008                    span: self.get_span(),
3009                    data: Rc::new(Number {
3010                        unit: Some(lhs.data.unit.unwrap() * rhs.data.unit.as_ref().unwrap()),
3011                        data: match &self.operator {
3012                            BinaryOperator::Mul(_) => NumberData::Multiply(lhs, rhs),
3013                            BinaryOperator::Div(_) => NumberData::Divide(lhs, rhs),
3014                            _ => unreachable!(),
3015                        },
3016                    }),
3017                    node: None,
3018                };
3019
3020                let mut node = HierarchyNode::new(NumberNode::from_expr(&expr, display, context));
3021                node.extend_children(lhs_node);
3022                node.extend_children(rhs_node);
3023
3024                expr.node = Some(node);
3025
3026                AnyExpr::Number(expr)
3027            }
3028        }
3029    }
3030}
3031
3032impl<const ITER: bool> Unroll for ImplicitIterator<ITER> {
3033    fn unroll(
3034        &self,
3035        context: &mut CompileContext,
3036        library: &Library,
3037        it_index: &HashMap<u8, usize>,
3038        display: Properties,
3039    ) -> AnyExpr {
3040        if self.exprs.collection.is_empty() {
3041            self.exprs.first.as_ref()
3042        } else {
3043            // Implicits always have id=0
3044            self.get(it_index[&0]).unwrap()
3045        }
3046        .unroll(context, library, it_index, display)
3047    }
3048}
3049
3050impl<const ITER: bool> Unroll for Expression<ITER> {
3051    fn unroll(
3052        &self,
3053        context: &mut CompileContext,
3054        library: &Library,
3055        it_index: &HashMap<u8, usize>,
3056        display: Properties,
3057    ) -> AnyExpr {
3058        match self {
3059            Expression::ImplicitIterator(it) => it.unroll(context, library, it_index, display),
3060            Expression::Binop(op) => op.unroll(context, library, it_index, display),
3061        }
3062    }
3063}
3064
3065// /// Unpacks the expressed type as a point collection.
3066// fn unpack_expression(
3067//     expr: &AnyExpr,
3068//     _context: &CompileContext,
3069// ) -> Result<Vec<Expr<Point>>, Error> {
3070//     match expr {
3071//
3072//         Type::Point => Ok(vec![expr.clone()]),
3073//         Type::PointCollection(l) => Ok((0..*l)
3074//             .map(|i| Expr {
3075//                 weight: FastFloat::One, // Weight propagated through `IndexCollection`
3076//                 data: Rc::new(UnrolledExpressionData::IndexCollection(expr.clone(), i)),
3077//                 ty: ty::POINT,
3078//                 span: expr.span,
3079//             })
3080//             .collect()),
3081//         ty => Err(Error::cannot_unpack(
3082//             expr.span,
3083//             *ty,
3084//         )),
3085//     }
3086// }
3087
3088/// A generic helper function for finding the string most similar to the given one
3089/// from a list of strings.
3090pub fn most_similar<'r, I: IntoIterator<Item = &'r T>, T: AsRef<str> + ?Sized + 'r>(
3091    expected: I,
3092    received: &str,
3093) -> Option<&'r T> {
3094    #[allow(clippy::cast_possible_truncation)]
3095    expected
3096        .into_iter()
3097        .map(|v| {
3098            (
3099                v,
3100                (strsim::jaro(v.as_ref(), received) * 1000.0).floor() as i64,
3101            )
3102        })
3103        .filter(|v| v.1 > 600)
3104        .max_by_key(|v| v.1)
3105        .map(|v| v.0)
3106}
3107
3108/// Properties, commonly used for display options.
3109#[derive(Debug)]
3110pub struct Properties {
3111    /// (normalized name)-(span, used-name, value) pairs.
3112    props: HashMap<String, (Span, String, PropertyValue)>,
3113    /// Whether the properties are safe to close.
3114    finished: bool,
3115    /// Errors encountered when parsing properties
3116    errors: Vec<Error>,
3117    /// Expected properties (not mandatory). Used for finding most similar
3118    /// properties to the ones that were never read.
3119    expected: Vec<&'static str>,
3120}
3121
3122impl Display for Properties {
3123    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
3124        write!(f, "[")?;
3125
3126        for (k, v) in &self.props {
3127            write!(f, "{k} = {}, ", v.1)?;
3128        }
3129
3130        write!(f, "]")
3131    }
3132}
3133
3134impl Clone for Properties {
3135    fn clone(&self) -> Self {
3136        Self {
3137            props: self.props.clone(),
3138            finished: false,
3139            errors: Vec::new(),
3140            expected: Vec::new(),
3141        }
3142    }
3143}
3144
3145// Just in case.
3146#[allow(clippy::derivable_impls)]
3147impl Default for Properties {
3148    fn default() -> Self {
3149        Self {
3150            props: HashMap::new(),
3151            finished: false,
3152            errors: Vec::new(),
3153            expected: Vec::new(),
3154        }
3155    }
3156}
3157
3158impl Properties {
3159    fn normalize(property: &str) -> String {
3160        property
3161            .chars()
3162            .filter(|c| *c != '_')
3163            .map(|c| c.to_ascii_lowercase())
3164            .collect()
3165    }
3166
3167    /// Finish parsing these properties and submit all their errors.
3168    pub fn finish(mut self, context: &CompileContext) {
3169        self.finished = true;
3170
3171        let props = mem::take(&mut self.props);
3172        let expected = mem::take(&mut self.expected);
3173
3174        self.errors.extend(props.into_values().map(|value| {
3175            let suggested = most_similar(expected.iter().copied(), &value.1);
3176
3177            Error::UnexpectedDisplayOption {
3178                error_span: value.0,
3179                option: value.1,
3180                suggested,
3181            }
3182        }));
3183
3184        context.extend_errors(mem::take(&mut self.errors));
3185    }
3186
3187    /// Get a property value by its name.
3188    #[must_use]
3189    pub fn get<T: FromProperty>(&mut self, property: &'static str) -> Property<T> {
3190        let norm = Self::normalize(property);
3191        if let Some((_, _, prop)) = self.props.remove(&norm) {
3192            let prop_span = prop.get_span();
3193
3194            Property {
3195                value: match T::from_property(prop) {
3196                    Ok(v) => Some(v),
3197                    Err(err) => {
3198                        self.errors.push(err);
3199                        None
3200                    }
3201                },
3202                span: Some(prop_span),
3203            }
3204        } else {
3205            self.expected.push(property);
3206
3207            Property {
3208                value: None,
3209                span: None,
3210            }
3211        }
3212    }
3213
3214    /// Ignore the given property.
3215    pub fn ignore(&mut self, property: &'static str) {
3216        self.props.remove(&Self::normalize(property));
3217    }
3218
3219    /// Add a property along with a value if it is not present yet.
3220    pub fn add_if_not_present(
3221        &mut self,
3222        property: &'static str,
3223        (key_span, value): (Span, PropertyValue),
3224    ) {
3225        self.props.entry(Self::normalize(property)).or_insert((
3226            key_span,
3227            property.to_string(),
3228            value,
3229        ));
3230    }
3231
3232    /// Merge the properties with other properties. Automatically finished the other properties.
3233    /// If there are collisions, `other` overwrites current values.
3234    #[must_use]
3235    pub fn merge_with(mut self, mut other: Properties) -> Self {
3236        self.errors.extend(mem::take(&mut other.errors));
3237
3238        for (k, v) in mem::take(&mut other.props) {
3239            self.props.insert(k, v);
3240        }
3241
3242        // no finish(), because that would require CompileContext. Here, however, no errors would happen anyway.
3243        other.finished = true;
3244
3245        self
3246    }
3247
3248    /// Ignore all unread properties.
3249    fn ignore_all(&mut self) {
3250        self.props.clear();
3251    }
3252}
3253
3254impl From<Option<DisplayProperties>> for Properties {
3255    fn from(value: Option<DisplayProperties>) -> Self {
3256        Self {
3257            props: value
3258                .into_iter()
3259                .flat_map(|x| x.properties.into_parsed_iter())
3260                .map(|v| {
3261                    (
3262                        Self::normalize(&v.name.ident),
3263                        (v.name.span, v.name.ident.clone(), v.value.clone()),
3264                    )
3265                })
3266                .collect(),
3267            finished: false,
3268            errors: Vec::new(),
3269            expected: Vec::new(),
3270        }
3271    }
3272}
3273
3274impl Drop for Properties {
3275    fn drop(&mut self) {
3276        if !self.finished {
3277            eprintln!(
3278                "Properties dropped before finishing parsing: {:#?}. Please report this error.",
3279                self.props
3280            );
3281        }
3282    }
3283}
3284
3285/// A single property with an optional value and an optional span.
3286#[derive(Debug, Clone)]
3287pub struct Property<T> {
3288    value: Option<T>,
3289    span: Option<Span>,
3290}
3291
3292impl<T> Property<T> {
3293    /// Get the property's value, consuming it.
3294    #[must_use]
3295    pub fn get(self) -> Option<T> {
3296        self.value
3297    }
3298
3299    /// Get the property's value or a default if the value is not present.
3300    #[must_use]
3301    pub fn get_or(self, default: T) -> T {
3302        self.value.unwrap_or(default)
3303    }
3304
3305    /// Get the property's span if it exists.
3306    #[must_use]
3307    pub fn get_span(&self) -> Option<Span> {
3308        self.span
3309    }
3310
3311    /// Make this property into a [`MaybeUnset`]
3312    #[must_use]
3313    pub fn maybe_unset(self, default: T) -> MaybeUnset<T> {
3314        let mut value = MaybeUnset::new(default);
3315        value.try_set(self.get());
3316
3317        value
3318    }
3319}
3320
3321impl<T> Property<Result<T, Error>> {
3322    /// Get the value or, in case of an error, a default alternative.
3323    #[must_use]
3324    pub fn ok_or(self, default: T) -> T {
3325        self.value.and_then(Result::ok).unwrap_or(default)
3326    }
3327}
3328
3329/// Create a named variable from the unrolled expression in a `let` statement.
3330fn create_variable_named(
3331    stat: &LetStatement,
3332    context: &mut CompileContext,
3333    named: &NamedIdent,
3334    mut rhs_unrolled: AnyExpr,
3335    variable_nodes: &mut Vec<Box<dyn Node>>,
3336) -> Result<(), Error> {
3337    let convert = if let AnyExpr::PointCollection(pc) = &mut rhs_unrolled {
3338        if pc.data.length == 1 {
3339            true
3340        } else {
3341            if let Some(node) = &mut pc.node {
3342                if let Some(mut props) = node.root.props.take() {
3343                    let _ = props.get::<Result<SpannedMathString, Error>>("default-label");
3344                    props.finish(context);
3345                }
3346            }
3347
3348            // Point collection variables are ambiguous and therefore cause compilation errors.
3349            // They do not, however prevent the program from running properly.
3350            context.push_error(Error::InvalidPC {
3351                error_span: stat.get_span(),
3352            });
3353            false
3354        }
3355    } else {
3356        false
3357    };
3358
3359    if convert {
3360        rhs_unrolled = rhs_unrolled.convert_to(Type::Point, context);
3361    }
3362
3363    match context.variables.entry(named.ident.clone()) {
3364        // If the variable already exists, it's a redefinition error.
3365        Entry::Occupied(entry) => Err(Error::RedefinedVariable {
3366            defined_at: entry.get().get_variable_span(),
3367            error_span: stat.get_span(),
3368            variable_name: entry.key().clone(),
3369        }),
3370        // Otherwise, create a new variable
3371        Entry::Vacant(entry) => {
3372            variable_nodes.extend(rhs_unrolled.replace_node(None).map(AnyExprNode::to_dyn));
3373
3374            let var = rhs_unrolled.make_variable(entry.key().clone());
3375            entry.insert(var);
3376
3377            Ok(())
3378        }
3379    }
3380}
3381
3382/// Create a point collection variable based from an unrolled expression in a `let` statement.
3383/// If the `lhs` of let statement is a point collection, the `rhs` has to be unpacked.
3384fn create_variable_collection(
3385    stat: &LetStatement,
3386    context: &mut CompileContext,
3387    col: &PCToken,
3388    rhs_unrolled: AnyExpr,
3389    variable_nodes: &mut Vec<Box<dyn Node>>,
3390) -> Result<(), Error> {
3391    // let display = Properties::from(display);
3392
3393    let maybe_error = Error::CannotUnpack {
3394        error_span: rhs_unrolled.get_span(),
3395        ty: rhs_unrolled.get_type(),
3396        length: col.len(),
3397    };
3398
3399    let mut rhs = rhs_unrolled.convert::<PointCollection>(context);
3400
3401    if rhs.data.length != col.len()
3402        && !matches!(rhs.data.data, PointCollectionData::Generic(Generic::Dummy))
3403    {
3404        return Err(maybe_error);
3405    }
3406
3407    // let pt_node = if col.collection.len() == 1 {
3408    //     Some(FigureNode::new_point(
3409    //         rhs_unpacked.index(0),
3410    //         display,
3411    //         IdentOrItem::PointCollectionItem(col.collection[0].clone())
3412    //     )?)
3413    // } else {
3414    //     None
3415    // };
3416
3417    for (i, pt) in col.collection.iter().enumerate() {
3418        let id = format!("{pt}");
3419        let mut var = rhs.index_with_node(i);
3420        let mut pt_node = var
3421            .take_node()
3422            .unwrap_or(HierarchyNode::new(PointNode::from_expr(
3423                &var,
3424                Properties::default(),
3425                context,
3426            )));
3427
3428        match context.variables.entry(id.clone()) {
3429            // If the variable already exists, it's a redefinition error.
3430            Entry::Occupied(entry) => {
3431                return Err(Error::RedefinedVariable {
3432                    defined_at: entry.get().get_variable_span(),
3433                    error_span: stat.get_span(),
3434                    variable_name: id,
3435                })
3436            }
3437            // Otherwise, create a new variable
3438            Entry::Vacant(entry) => {
3439                pt_node.root.default_label = SpannedMathString::from(pt.clone());
3440
3441                variable_nodes.push(Box::new(pt_node));
3442
3443                let var = var.make_variable(entry.key().clone());
3444
3445                let var = AnyExpr::Point(var);
3446                entry.insert(var);
3447            }
3448        }
3449    }
3450
3451    variable_nodes.extend(rhs.take_node().map(|n| Box::new(n) as Box<dyn Node>));
3452
3453    Ok(())
3454}
3455
3456/// Create variables from a `let` statement.
3457fn create_variables(
3458    stat: &LetStatement,
3459    context: &mut CompileContext,
3460    library: &Library,
3461    external: Option<DisplayProperties>,
3462) -> Result<Vec<Box<dyn Node>>, Error> {
3463    let mut variable_nodes = Vec::new();
3464
3465    let tree = IterNode::from(&stat.expr);
3466
3467    let ind = if let Some(iter) = tree.first() {
3468        if stat.ident.len() == 1 {
3469            context.push_error(Error::LetStatUnexpectedIterator {
3470                var_span: stat.ident.get_span(),
3471                error_span: iter.span,
3472            });
3473
3474            // Ignore every but first entry in the iterator.
3475        }
3476
3477        for it in tree.iter() {
3478            if iter.id != it.id {
3479                context.push_error(Error::LetStatMoreThanOneIterator {
3480                    error_span: stat.expr.get_span(),
3481                    first_span: iter.span,
3482                    second_span: it.span,
3483                });
3484
3485                // Ignore every other iterator.
3486            }
3487
3488            for variant in &it.variants {
3489                if let Some(it2) = variant.first() {
3490                    context.push_error(Error::LetStatMoreThanOneIterator {
3491                        error_span: stat.expr.get_span(),
3492                        first_span: iter.span,
3493                        second_span: it2.span,
3494                    });
3495
3496                    // Ignore every other iterator.
3497                }
3498            }
3499        }
3500
3501        let mut lengths = HashMap::new();
3502        tree.get_iter_lengths(&mut lengths, stat.expr.get_span())?;
3503        let entry = lengths.get(&iter.id).unwrap();
3504
3505        if entry.0 != stat.ident.len() {
3506            return Err(Error::InconsistentIterators {
3507                first_span: stat.ident.get_span(),
3508                first_length: stat.ident.len(),
3509                occurred_span: entry.1,
3510                occurred_length: entry.0,
3511                error_span: stat.get_span(),
3512            });
3513        }
3514
3515        None
3516    } else {
3517        Some(HashMap::new())
3518    };
3519
3520    let mut it_index = IterTreeIterator::new(&tree);
3521
3522    // Iterate over each identifier.
3523    for def in stat.ident.iter() {
3524        let mut external = Properties::from(external.clone());
3525
3526        if def.name.is_named() {
3527            external.add_if_not_present(
3528                "default-label",
3529                (def.name.get_span(), PropertyValue::Ident(def.name.clone())),
3530            );
3531        }
3532
3533        let display = external.merge_with(Properties::from(def.display_properties.clone()));
3534
3535        let rhs_unrolled = stat.expr.unroll(
3536            context,
3537            library,
3538            ind.as_ref()
3539                .unwrap_or_else(|| it_index.get_currents().unwrap()),
3540            display,
3541        );
3542        it_index.next();
3543
3544        // println!("let {} = {rhs_unrolled}", def.name);
3545
3546        match &def.name {
3547            Ident::Named(named) => {
3548                create_variable_named(stat, context, named, rhs_unrolled, &mut variable_nodes)?;
3549            }
3550            Ident::Collection(col) => {
3551                create_variable_collection(stat, context, col, rhs_unrolled, &mut variable_nodes)?;
3552            }
3553        }
3554    }
3555
3556    Ok(variable_nodes)
3557}
3558
3559/// Unroll a ref statement.
3560fn unroll_ref(
3561    stat: &parser::Displayed<RefStatement>,
3562    context: &mut CompileContext,
3563    library: &Library,
3564) -> Result<Vec<Box<dyn Node>>, Error> {
3565    let mut nodes = Vec::new();
3566    let tree = IterNode::from(&stat.statement.operand);
3567
3568    // Check the lengths
3569    tree.get_iter_lengths(&mut HashMap::new(), stat.get_span())?;
3570
3571    // And create the index
3572    let mut index = IterTreeIterator::new(&tree);
3573
3574    while let Some(it_index) = index.get_currents() {
3575        let mut display = Properties::from(stat.properties.clone());
3576        let weight = display.get("weight").get_or(ProcNum::zero());
3577
3578        let mut expr = stat
3579            .statement
3580            .operand
3581            .unroll(context, library, it_index, display);
3582
3583        if let AnyExpr::PointCollection(pc) = &mut expr {
3584            if let Some(node) = pc.node.take() {
3585                if let Some(props) = node.root.props {
3586                    props.finish(context);
3587                }
3588            }
3589
3590            context.push_error(Error::InvalidPC {
3591                error_span: expr.get_span(),
3592            });
3593        }
3594
3595        let node = expr.replace_node(None).map(AnyExprNode::to_dyn);
3596        nodes.extend(node);
3597
3598        // If any weight is given, add a bias
3599        if !weight.is_zero() {
3600            context.push_rule(UnrolledRule {
3601                kind: UnrolledRuleKind::Bias(expr),
3602                inverted: false,
3603                weight,
3604            });
3605        }
3606
3607        index.next();
3608    }
3609
3610    Ok(nodes)
3611}
3612
3613/// Unroll a `let` statement.
3614fn unroll_let(
3615    stat: parser::Displayed<LetStatement>,
3616    context: &mut CompileContext,
3617    library: &Library,
3618) -> Result<Vec<Box<dyn Node>>, Error> {
3619    let parser::Displayed {
3620        properties,
3621        statement: mut stat,
3622    } = stat;
3623
3624    // First, we construct an iterator out of lhs
3625    let lhs: Expression<true> = Expression::ImplicitIterator(ImplicitIterator {
3626        exprs: Punctuated {
3627            first: Box::new(SimpleExpression {
3628                minus: None,
3629                kind: SimpleExpressionKind::Name(Name::Ident(stat.ident.first.name.clone())),
3630                exponent: None,
3631                display: None,
3632            }),
3633            collection: stat
3634                .ident
3635                .collection
3636                .iter()
3637                .map(|(p, i)| {
3638                    (
3639                        *p,
3640                        SimpleExpression {
3641                            minus: None,
3642                            kind: SimpleExpressionKind::Name(Name::Ident(i.name.clone())),
3643                            exponent: None,
3644                            display: None,
3645                        },
3646                    )
3647                })
3648                .collect(),
3649        },
3650    });
3651
3652    let stat_span = stat.get_span();
3653    let rule = mem::take(&mut stat.rule);
3654
3655    let mut nodes = create_variables(&stat, context, library, properties)?;
3656
3657    // Then, we run each rule through a tree iterator.
3658    if let Some((rule, expr)) = rule {
3659        let tree = IterNode::from2(&lhs, &expr);
3660
3661        // Check the lengths
3662        tree.get_iter_lengths(&mut HashMap::new(), stat_span)?;
3663
3664        // And create the index
3665        let mut index = IterTreeIterator::new(&tree);
3666
3667        while let Some(it_index) = index.get_currents() {
3668            nodes.push(unroll_rule(
3669                (
3670                    lhs.unroll(context, library, it_index, Properties::default()),
3671                    &rule,
3672                    expr.unroll(context, library, it_index, Properties::default()),
3673                ),
3674                context,
3675                library,
3676                stat_span,
3677                false,
3678                Properties::from(None),
3679            ));
3680
3681            index.next();
3682        }
3683    }
3684
3685    Ok(nodes)
3686}
3687
3688/// Unroll an equality rule.
3689fn unroll_eq(
3690    lhs: AnyExpr,
3691    rhs: AnyExpr,
3692    context: &mut CompileContext,
3693    full_span: Span,
3694    inverted: bool,
3695    display: Properties,
3696) -> Box<dyn Node> {
3697    let lhs_type = lhs.get_type();
3698    let rhs_type = rhs.get_type();
3699
3700    if (lhs_type == ty::collection(2) && rhs_type == ty::collection(2))
3701        || (lhs_type == ty::collection(2) && rhs_type == ty::SCALAR_UNKNOWN)
3702        || (lhs_type == ty::SCALAR_UNKNOWN && rhs_type == ty::collection(2))
3703    {
3704        // AB = CD must have different logic as it's implied that this means "equality of distances".
3705        let lhs = lhs
3706            .convert(context)
3707            .convert_unit(Some(unit::DISTANCE), context);
3708        let rhs = rhs
3709            .convert(context)
3710            .convert_unit(Some(unit::DISTANCE), context);
3711        context.scalar_eq_display(lhs, rhs, inverted, display)
3712    } else if lhs_type == ty::collection(1) && rhs_type == ty::collection(1) {
3713        let lhs = lhs.convert(context);
3714        let rhs = rhs.convert(context);
3715
3716        context.point_eq_display(lhs, rhs, inverted, display)
3717    } else {
3718        // If any of the two types can be cast onto the other, cast and compare.
3719        let (lhs, rhs, new_type) = if rhs.can_convert_to(lhs_type) {
3720            (lhs, rhs.convert_to(lhs_type, context), lhs_type)
3721        } else if lhs.can_convert_to(rhs_type) {
3722            (lhs.convert_to(rhs_type, context), rhs, rhs_type)
3723        } else {
3724            context.push_error(Error::InconsistentTypes {
3725                expected: (lhs_type, Box::new(lhs.get_span())),
3726                got: (rhs_type, Box::new(rhs.get_span())),
3727                error_span: Box::new(full_span),
3728            });
3729
3730            // "Cast" rhs to lhs.
3731            (
3732                lhs,
3733                AnyExpr::Unknown(Expr {
3734                    span: rhs.get_span(),
3735                    data: Rc::new(Unknown::dummy()),
3736                    node: None,
3737                })
3738                .convert_to(lhs_type, context),
3739                lhs_type,
3740            )
3741        };
3742
3743        match new_type {
3744            Type::Point => {
3745                let lhs = lhs.convert(context);
3746                let rhs = rhs.convert(context);
3747
3748                context.point_eq_display(lhs, rhs, inverted, display)
3749            }
3750            Type::Number(_) => {
3751                let lhs = lhs.convert(context);
3752                let rhs = rhs.convert(context);
3753
3754                context.scalar_eq_display(lhs, rhs, inverted, display)
3755            }
3756            ty => {
3757                if ty != Type::Unknown {
3758                    context.push_error(Error::ComparisonDoesNotExist {
3759                        error_span: full_span,
3760                        ty,
3761                    });
3762                }
3763
3764                // Pretend there is no rule.
3765                context.scalar_eq_display(
3766                    Expr::new_spanless(Number::dummy()),
3767                    Expr::new_spanless(Number::dummy()),
3768                    inverted,
3769                    display,
3770                )
3771            }
3772        }
3773    }
3774}
3775
3776/// Unroll a greater-than rule.
3777fn unroll_gt(
3778    lhs: Expr<Number>,
3779    rhs: Expr<Number>,
3780    context: &mut CompileContext,
3781    full_span: Span,
3782    inverted: bool,
3783    display: Properties,
3784) -> Box<dyn Node> {
3785    if lhs.data.unit.is_some() {
3786        let rhs = if rhs.can_convert_unit(lhs.data.unit) {
3787            rhs.convert_unit(lhs.data.unit, context)
3788        } else {
3789            context.push_error(Error::InconsistentTypes {
3790                expected: (lhs.get_value_type(), Box::new(lhs.span)),
3791                got: (rhs.get_value_type(), Box::new(rhs.span)),
3792                error_span: Box::new(full_span),
3793            });
3794
3795            Expr {
3796                span: rhs.span,
3797                node: rhs.node,
3798                data: Rc::new(Number::dummy()),
3799            }
3800            .convert_unit(lhs.data.unit, context)
3801        };
3802
3803        context.gt_display(lhs, rhs, inverted, display)
3804    } else if rhs.data.unit.is_some() {
3805        let lhs = lhs.convert_unit(rhs.data.unit, context);
3806        context.gt_display(lhs, rhs, inverted, display)
3807    } else {
3808        let lhs = lhs.convert_unit(Some(unit::SCALAR), context);
3809        let rhs = rhs.convert_unit(Some(unit::SCALAR), context);
3810        context.gt_display(lhs, rhs, inverted, display)
3811    }
3812}
3813
3814/// Unroll a generic rule.
3815fn unroll_rule(
3816    (lhs, op, rhs): (AnyExpr, &RuleOperator, AnyExpr),
3817    context: &mut CompileContext,
3818    library: &Library,
3819    full_span: Span,
3820    inverted: bool,
3821    mut display: Properties,
3822) -> Box<dyn Node> {
3823    match op {
3824        RuleOperator::Predefined(pre) => match pre {
3825            PredefinedRuleOperator::Eq(_) => {
3826                unroll_eq(lhs, rhs, context, full_span, inverted, display)
3827            }
3828            PredefinedRuleOperator::Lt(_) => unroll_gt(
3829                rhs.convert(context),
3830                lhs.convert(context),
3831                context,
3832                full_span,
3833                inverted,
3834                display,
3835            ),
3836            PredefinedRuleOperator::Gt(_) => unroll_gt(
3837                lhs.convert(context),
3838                rhs.convert(context),
3839                context,
3840                full_span,
3841                inverted,
3842                display,
3843            ),
3844            PredefinedRuleOperator::Lteq(_) => unroll_gt(
3845                lhs.convert(context),
3846                rhs.convert(context),
3847                context,
3848                full_span,
3849                !inverted,
3850                display,
3851            ),
3852            PredefinedRuleOperator::Gteq(_) => unroll_gt(
3853                rhs.convert(context),
3854                lhs.convert(context),
3855                context,
3856                full_span,
3857                !inverted,
3858                display,
3859            ),
3860        },
3861        RuleOperator::Defined(op) => {
3862            let weight = display.get("weight").get_or(ProcNum::one());
3863
3864            let overload = match library.get_rule(op.ident.as_str()) {
3865                Ok(func) => {
3866                    if let Some(overload) = func.get_overload(&lhs, &rhs) {
3867                        overload
3868                    } else {
3869                        context.push_error(Error::OverloadNotFound {
3870                            error_span: op.span,
3871                            function_name: op.ident.clone(),
3872                            params: vec![lhs.get_type(), rhs.get_type()],
3873                        });
3874
3875                        // Pretend the rule doesn't exist.
3876                        display.finish(context);
3877                        return Box::new(EmptyNode);
3878                    }
3879                }
3880                Err(suggested) => {
3881                    context.push_error(Error::UndefinedFunction {
3882                        error_span: op.span,
3883                        function_name: op.ident.clone(),
3884                        suggested,
3885                    });
3886
3887                    // Pretend the rule doesn't exist.
3888                    display.finish(context);
3889                    return Box::new(EmptyNode);
3890                }
3891            };
3892
3893            overload.unroll(lhs, rhs, context, display, inverted, weight)
3894        }
3895        RuleOperator::Inverted(op) => unroll_rule(
3896            (lhs, &op.operator, rhs),
3897            context,
3898            library,
3899            full_span,
3900            !inverted,
3901            display,
3902        ),
3903    }
3904}
3905
3906/// Unroll a general rule statement.
3907fn unroll_rule_statement(
3908    rule: &parser::Displayed<RuleStatement>,
3909    context: &mut CompileContext,
3910    library: &Library,
3911) -> Result<Vec<Box<dyn Node>>, Error> {
3912    let mut nodes = Vec::new();
3913    let parser::Displayed {
3914        properties,
3915        statement: rule,
3916    } = rule;
3917
3918    let firsts = Some(&rule.first)
3919        .into_iter()
3920        .chain(rule.rules.iter().map(|v| &v.1));
3921
3922    for (lhs, op, rhs) in firsts
3923        .zip(rule.rules.iter())
3924        .map(|(lhs, (op, rhs))| (lhs, op, rhs))
3925    {
3926        let tree = IterNode::from2(lhs, rhs);
3927        let full_span = lhs.get_span().join(rhs.get_span());
3928        tree.get_iter_lengths(&mut HashMap::new(), full_span)?;
3929
3930        let mut it_index = IterTreeIterator::new(&tree);
3931
3932        while let Some(index) = it_index.get_currents() {
3933            nodes.push(unroll_rule(
3934                (
3935                    lhs.unroll(context, library, index, Properties::default()),
3936                    op,
3937                    rhs.unroll(context, library, index, Properties::default()),
3938                ),
3939                context,
3940                library,
3941                full_span,
3942                false,
3943                Properties::from(properties.clone()),
3944            ));
3945
3946            it_index.next();
3947        }
3948    }
3949
3950    Ok(nodes)
3951}
3952
3953/// Unrolls the given script. All iterators are expanded and all conversions applied. The output can be immediately compiled.
3954///
3955/// # Errors
3956/// Specific error descriptions are in `ScriptError` documentation.
3957pub fn unroll(input: &str) -> Result<(CompileContext, CollectionNode), Vec<Error>> {
3958    // Unfortunately, due to how context-dependent geoscript is, the code must be compiled immediately after parsing.
3959    let mut context = CompileContext::new();
3960    let library = Library::new();
3961
3962    let mut figure = CollectionNode::new();
3963
3964    let tokens = match token::tokenize(input) {
3965        Ok(v) => v,
3966        Err(err) => return Err(vec![err]),
3967    };
3968    let mut input = InputStream::new(&tokens);
3969
3970    let mut statements = Vec::new();
3971
3972    while !input.eof() {
3973        statements.push(match input.parse() {
3974            Ok(v) => v,
3975            Err(err) => return Err(vec![err]),
3976        });
3977    }
3978
3979    let mut flags = FlagSetConstructor::new()
3980        .add_set("optimizations", FlagSetConstructor::new())
3981        .add_set(
3982            "language",
3983            FlagSetConstructor::new().add_bool_def("complex_numbers", false),
3984        )
3985        .add_bool_def("point_inequalities", true)
3986        .finish();
3987
3988    for flag in statements.iter().filter_map(Statement::as_flag) {
3989        flags::set_flag(&mut flags, flag, &context);
3990    }
3991
3992    context.flags = flags;
3993
3994    // If complex numbers are enabled, create the complex unit variable.
3995    let enable_complex = context.flags["language"].as_set().unwrap()["complex_numbers"]
3996        .kind
3997        .as_setting()
3998        .unwrap();
3999
4000    if enable_complex.get_value().unwrap().as_bool().unwrap() {
4001        context.variables.insert(
4002            String::from("i"),
4003            AnyExpr::Number(Expr {
4004                span: enable_complex.get_span().unwrap(),
4005                data: Rc::new(Number {
4006                    unit: Some(unit::SCALAR),
4007                    data: NumberData::Number(ProcNum::i()),
4008                }),
4009                node: None,
4010            }),
4011        );
4012    }
4013
4014    for stat in statements {
4015        // Unroll the statement
4016        match stat {
4017            Statement::Noop(_) | Statement::Flag(_) => (),
4018            Statement::Let(stat) => match unroll_let(stat, &mut context, &library) {
4019                Ok(nodes) => {
4020                    for node in nodes {
4021                        figure.push_boxed(node);
4022                    }
4023                }
4024                Err(err) => context.push_error(err),
4025            },
4026            Statement::Rule(stat) => match unroll_rule_statement(&stat, &mut context, &library) {
4027                Ok(nodes) => {
4028                    for node in nodes {
4029                        figure.push_boxed(node);
4030                    }
4031                }
4032                Err(err) => context.push_error(err),
4033            },
4034            Statement::Ref(stat) => match unroll_ref(&stat, &mut context, &library) {
4035                Ok(nodes) => {
4036                    for node in nodes {
4037                        figure.push_boxed(node);
4038                    }
4039                }
4040                Err(err) => context.push_error(err),
4041            },
4042        }
4043    }
4044
4045    // for x in context.rules.borrow().iter() {
4046    //     println!("{x}");
4047    // }
4048
4049    if context.valid() {
4050        Ok((context, figure))
4051    } else {
4052        Err(context.take_errors())
4053    }
4054}