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(Refer::new(
24                    inner.to_string(),
25                    pair.into(),
26                ))),
27            },
28            _ => Err(ParseError::UnknownType(Refer::new(
29                inner.to_string(),
30                pair.into(),
31            ))),
32        }
33    }
34}
35
36impl Parse for QuantityType {
37    fn parse(pair: Pair) -> ParseResult<Self> {
38        Parser::ensure_rule(&pair, Rule::quantity_type);
39        Ok(match pair.as_str() {
40            "Scalar" => QuantityType::Scalar,
41            "Length" => QuantityType::Length,
42            "Area" => QuantityType::Area,
43            "Angle" => QuantityType::Angle,
44            "Volume" => QuantityType::Volume,
45            "Weight" => QuantityType::Weight,
46            "Density" => QuantityType::Density,
47            _ => unreachable!("Expected type, found {:?}", pair.as_str()),
48        })
49    }
50}
51
52impl Parse for TypeAnnotation {
53    fn parse(pair: Pair) -> ParseResult<Self> {
54        Ok(Self(Refer::new(Type::parse(pair.clone())?, pair.into())))
55    }
56}
57
58#[test]
59fn named_tuple_type() {
60    use crate::parser::*;
61    use crate::ty::Ty;
62
63    let type_annotation =
64        Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "(x: Integer, y: String)", 0)
65            .expect("test error");
66    assert_eq!(type_annotation.ty().to_string(), "(x: Integer, y: String)");
67    assert_eq!(
68        type_annotation.ty(),
69        Type::Tuple(
70            TupleType {
71                named: [("x", Type::Integer), ("y", Type::String)]
72                    .into_iter()
73                    .map(|(id, ty)| (id.into(), ty))
74                    .collect(),
75                ..Default::default()
76            }
77            .into()
78        )
79    );
80}