Skip to main content

microcad_lang/parse/
type.rs

1// Copyright © 2025-2026 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::{parse::*, parser::*, src_ref::*, ty::*};
5use microcad_syntax::ast;
6use std::str::FromStr;
7
8impl Type {
9    fn parse_str(ty: &str, src_ref: SrcRef) -> ParseResult<Self> {
10        if let Some(dimensions) = ty.strip_prefix("Matrix") {
11            let (x, y) = dimensions
12                .split_once('x')
13                .unwrap_or((dimensions, dimensions));
14            let x = usize::from_str(x).map_err(|_| {
15                ParseError::InvalidMatrixType(Refer::new(ty.to_string(), src_ref.clone()))
16            })?;
17            let y = usize::from_str(y).map_err(|_| {
18                ParseError::InvalidMatrixType(Refer::new(ty.to_string(), src_ref.clone()))
19            })?;
20            return Ok(Type::Matrix(MatrixType::new(x, y)));
21        }
22
23        match ty {
24            "Color" => Ok(Type::Tuple(Box::new(TupleType::new_color()))),
25            "Vec2" => Ok(Type::Tuple(Box::new(TupleType::new_vec2()))),
26            "Vec3" => Ok(Type::Tuple(Box::new(TupleType::new_vec3()))),
27            "Size2" => Ok(Type::Tuple(Box::new(TupleType::new_size2()))),
28            "Integer" => Ok(Type::Integer),
29            "Bool" => Ok(Type::Bool),
30            "String" => Ok(Type::String),
31            "Scalar" => Ok(Type::Quantity(QuantityType::Scalar)),
32            "Length" => Ok(Type::Quantity(QuantityType::Length)),
33            "Area" => Ok(Type::Quantity(QuantityType::Area)),
34            "Angle" => Ok(Type::Quantity(QuantityType::Angle)),
35            "Volume" => Ok(Type::Quantity(QuantityType::Volume)),
36            "Weight" => Ok(Type::Quantity(QuantityType::Weight)),
37            "Density" => Ok(Type::Quantity(QuantityType::Density)),
38            _ => Err(ParseError::UnknownType(Refer::new(ty.to_string(), src_ref))),
39        }
40    }
41}
42
43impl FromAst for Type {
44    type AstNode = ast::Type;
45
46    fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
47        Ok(match node {
48            ast::Type::Single(ty) => {
49                Type::parse_str(ty.name.as_str(), context.src_ref(&node.span()))?
50            }
51            ast::Type::Array(ty) => Type::Array(Box::new(Type::from_ast(&ty.inner, context)?)),
52            ast::Type::Tuple(ty) => Type::Tuple(Box::new(TupleType::from_ast(ty, context)?)),
53        })
54    }
55}
56
57impl FromAst for TypeAnnotation {
58    type AstNode = ast::Type;
59
60    fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
61        Ok(TypeAnnotation(Refer::new(
62            Type::from_ast(node, context)?,
63            context.src_ref(&node.span()),
64        )))
65    }
66}