microcad_lang/parse/
lang_type.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::{parse::*, parser::*, syntax::*, ty::*};
5
6impl Parse for TupleType {
7    fn parse(pair: Pair) -> ParseResult<Self> {
8        use crate::ty::Ty;
9        Parser::ensure_rule(&pair, Rule::tuple_type);
10
11        match pair.as_str() {
12            "Color" => Ok(TupleType::new_color()),
13            "Vec2" => Ok(TupleType::new_vec2()),
14            "Vec3" => Ok(TupleType::new_vec3()),
15            "Size2" => Ok(TupleType::new_size2()),
16            _ => {
17                let mut named = std::collections::HashMap::new();
18                let mut unnamed = std::collections::HashSet::new();
19
20                pair.inner().try_for_each(|pair| {
21                    let mut inner = pair.inner();
22                    let next = inner.next().expect("Identifier or type expected");
23                    if let Ok(id) = Identifier::parse(next.clone()) {
24                        if named
25                            .insert(
26                                id.clone(),
27                                TypeAnnotation::parse(
28                                    inner.next().expect("Identifier or type expected"),
29                                )?
30                                .ty(),
31                            )
32                            .is_some()
33                        {
34                            return Err(ParseError::DuplicateTupleIdentifier(id));
35                        }
36                    } else {
37                        let ty = TypeAnnotation::parse(next)?.ty();
38                        if !unnamed.insert(ty.clone()) {
39                            return Err(ParseError::DuplicateTupleType(Refer::new(
40                                ty,
41                                pair.clone().into(),
42                            )));
43                        }
44                    }
45
46                    Ok::<(), ParseError>(())
47                })?;
48
49                Ok(Self { named, unnamed })
50            }
51        }
52    }
53}
54
55impl Parse for MatrixType {
56    fn parse(pair: Pair) -> ParseResult<Self> {
57        Parser::ensure_rule(&pair, Rule::matrix_type);
58
59        let mut m: Option<usize> = None;
60        let mut n: Option<usize> = None;
61
62        for p in pair.inner() {
63            match p.as_rule() {
64                Rule::int => match m {
65                    None => m = Some(p.as_str().parse().expect("Valid integer")),
66                    Some(_) => n = Some(p.as_str().parse().expect("Valid integer")),
67                },
68                _ => unreachable!(),
69            }
70        }
71
72        let m = m.expect("M");
73
74        Ok(Self {
75            rows: m,
76            columns: n.unwrap_or(m),
77        })
78    }
79}
80
81#[test]
82fn array_type() {
83    use crate::parser::{Parser, Rule};
84    use crate::ty::Ty;
85
86    let type_annotation =
87        Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "[Integer]", 0).expect("test error");
88    assert_eq!(type_annotation.ty().to_string(), "[Integer]");
89    assert_eq!(type_annotation.ty(), Type::Array(Box::new(Type::Integer)));
90}
91
92#[test]
93fn matrix_type() {
94    use crate::parser::*;
95    use crate::ty::Ty;
96
97    let type_annotation =
98        Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "Matrix4x3", 0).expect("test error");
99    assert_eq!(type_annotation.ty().to_string(), "Matrix4x3");
100    assert_eq!(
101        type_annotation.ty(),
102        Type::Matrix(MatrixType {
103            rows: 4,
104            columns: 3,
105        })
106    );
107}