Skip to main content

microcad_lang/parse/
type.rs

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