microcad_lang/parse/
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::*, src_ref::*, ty::*};
5
6impl Parse for Type {
7    fn parse(pair: Pair) -> ParseResult<Self> {
8        Parser::ensure_rule(&pair, Rule::r#type);
9        let inner = pair.inner().next().expect("Expected type");
10
11        match inner.as_rule() {
12            Rule::array_type => Ok(Type::Array(Box::new(Type::parse(
13                inner.inner().next().expect("Type"),
14            )?))),
15            Rule::tuple_type => Ok(Type::Tuple(TupleType::parse(inner)?.into())),
16            Rule::matrix_type => Ok(Type::Matrix(MatrixType::parse(inner)?)),
17            Rule::quantity_type => Ok(Type::Quantity(QuantityType::parse(inner)?)),
18            Rule::base_type => match inner.as_str() {
19                // Builtin types.
20                "Integer" => Ok(Type::Integer),
21                "Bool" => Ok(Type::Bool),
22                "String" => Ok(Type::String),
23                _ => Err(ParseError::UnknownType(inner.to_string())),
24            },
25            _ => Err(ParseError::UnknownType(inner.to_string())),
26        }
27    }
28}
29
30impl Parse for QuantityType {
31    fn parse(pair: Pair) -> ParseResult<Self> {
32        Parser::ensure_rule(&pair, Rule::quantity_type);
33        Ok(match pair.as_str() {
34            "Scalar" => QuantityType::Scalar,
35            "Length" => QuantityType::Length,
36            "Area" => QuantityType::Area,
37            "Angle" => QuantityType::Angle,
38            "Volume" => QuantityType::Volume,
39            "Weight" => QuantityType::Weight,
40            "Density" => QuantityType::Density,
41            _ => unreachable!("Expected type, found {:?}", pair.as_str()),
42        })
43    }
44}
45
46impl Parse for TypeAnnotation {
47    fn parse(pair: Pair) -> ParseResult<Self> {
48        Ok(Self(Refer::new(Type::parse(pair.clone())?, pair.into())))
49    }
50}
51
52#[test]
53fn named_tuple_type() {
54    use crate::parser::*;
55    use crate::ty::Ty;
56
57    let type_annotation =
58        Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "(x: Integer, y: String)", 0)
59            .expect("test error");
60    assert_eq!(type_annotation.ty().to_string(), "(x: Integer, y: String)");
61    assert_eq!(
62        type_annotation.ty(),
63        Type::Tuple(
64            TupleType {
65                named: [("x", Type::Integer), ("y", Type::String)]
66                    .into_iter()
67                    .map(|(id, ty)| (id.into(), ty))
68                    .collect(),
69                ..Default::default()
70            }
71            .into()
72        )
73    );
74}