Skip to main content

harn_parser/builtin_signatures/
types.rs

1//! Re-exports of builtin signature shape types from `harn-builtin-meta`, plus
2//! parser-local conversion helpers from the const IR (`Ty`) to the runtime
3//! IR (`TypeExpr`).
4//!
5//! The const-constructible types live in `harn-builtin-meta` (a dep-free
6//! crate consumed by both the parser and `harn-vm`). Conversion to the
7//! parser's owned `TypeExpr` requires types that are private to this crate,
8//! so it lives here as an extension trait.
9
10use crate::ast::{ShapeField, TypeExpr};
11
12pub use harn_builtin_meta::{
13    BuiltinMetadata, BuiltinSignature, Param, ShapeFieldDescriptor, Ty, TY_ANY, TY_BOOL, TY_BYTES,
14    TY_BYTES_OR_NIL, TY_CLOSURE, TY_DICT, TY_DICT_OR_NIL, TY_DURATION, TY_FLOAT, TY_INT,
15    TY_INT_OR_NIL, TY_LIST, TY_NEVER, TY_NIL, TY_NUMBER, TY_STRING, TY_STRING_OR_NIL,
16};
17
18/// Convert a const-IR [`Ty`] into the parser's owned [`TypeExpr`]. Generic
19/// references stay as `Named(name)` so the checker's existing scope-based
20/// generic-param resolution applies.
21pub fn ty_to_type_expr(ty: &Ty) -> TypeExpr {
22    match ty {
23        Ty::Named(name) => TypeExpr::Named((*name).into()),
24        Ty::Generic(name) => TypeExpr::Named((*name).into()),
25        Ty::Any => TypeExpr::Named("any".into()),
26        Ty::Optional(inner) => {
27            TypeExpr::Union(vec![ty_to_type_expr(inner), TypeExpr::Named("nil".into())])
28        }
29        Ty::Apply(name, args) => TypeExpr::Applied {
30            name: (*name).into(),
31            args: args.iter().map(ty_to_type_expr).collect(),
32        },
33        Ty::Union(members) => TypeExpr::Union(members.iter().map(ty_to_type_expr).collect()),
34        Ty::Fn(params, return_type) => TypeExpr::FnType {
35            params: params.iter().map(ty_to_type_expr).collect(),
36            return_type: Box::new(ty_to_type_expr(return_type)),
37        },
38        Ty::Shape(fields) => TypeExpr::Shape(
39            fields
40                .iter()
41                .map(|f| ShapeField {
42                    name: f.name.into(),
43                    type_expr: ty_to_type_expr(&f.ty),
44                    optional: f.optional,
45                })
46                .collect(),
47        ),
48        Ty::SchemaOf(name) => TypeExpr::Applied {
49            name: "Schema".into(),
50            args: vec![TypeExpr::Named((*name).into())],
51        },
52        Ty::Never => TypeExpr::Never,
53        Ty::LitInt(v) => TypeExpr::LitInt(*v),
54        Ty::LitString(s) => TypeExpr::LitString((*s).into()),
55    }
56}
57
58/// Parser-side extension methods on [`Ty`] and [`BuiltinSignature`] that
59/// depend on the parser's owned AST types (kept out of `harn-builtin-meta`
60/// so that crate stays dep-free).
61pub trait TyExt {
62    /// Materialize as a runtime [`TypeExpr`].
63    fn to_type_expr(&self) -> TypeExpr;
64}
65
66impl TyExt for Ty {
67    fn to_type_expr(&self) -> TypeExpr {
68        ty_to_type_expr(self)
69    }
70}
71
72pub trait BuiltinSignatureExt {
73    /// Materialize per-parameter types as owned [`TypeExpr`]s for the type
74    /// checker's call-site validation.
75    fn param_type_exprs(&self) -> Vec<TypeExpr>;
76    /// Owned [`TypeExpr`] return type.
77    fn return_type_expr(&self) -> TypeExpr;
78}
79
80impl BuiltinSignatureExt for BuiltinSignature {
81    fn param_type_exprs(&self) -> Vec<TypeExpr> {
82        self.params.iter().map(|p| ty_to_type_expr(&p.ty)).collect()
83    }
84
85    fn return_type_expr(&self) -> TypeExpr {
86        ty_to_type_expr(&self.returns)
87    }
88}