use crate::ast::{ShapeField, TypeExpr};
#[derive(Debug, Clone, Copy)]
pub struct BuiltinSignature {
pub name: &'static str,
pub params: &'static [Param],
pub returns: Ty,
pub type_params: &'static [&'static str],
pub has_rest: bool,
pub where_clauses: &'static [(&'static str, &'static str)],
}
#[derive(Debug, Clone, Copy)]
pub struct Param {
pub name: &'static str,
pub ty: Ty,
pub optional: bool,
}
impl Param {
pub const fn new(name: &'static str, ty: Ty) -> Self {
Self {
name,
ty,
optional: false,
}
}
pub const fn optional(name: &'static str, ty: Ty) -> Self {
Self {
name,
ty,
optional: true,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Ty {
Named(&'static str),
Generic(&'static str),
Any,
Optional(&'static Ty),
Apply(&'static str, &'static [Ty]),
Union(&'static [Ty]),
Fn(&'static [Ty], &'static Ty),
Shape(&'static [ShapeFieldDescriptor]),
SchemaOf(&'static str),
Never,
LitInt(i64),
LitString(&'static str),
}
#[derive(Debug, Clone, Copy)]
pub struct ShapeFieldDescriptor {
pub name: &'static str,
pub ty: Ty,
pub optional: bool,
}
impl ShapeFieldDescriptor {
pub const fn new(name: &'static str, ty: Ty) -> Self {
Self {
name,
ty,
optional: false,
}
}
pub const fn optional(name: &'static str, ty: Ty) -> Self {
Self {
name,
ty,
optional: true,
}
}
}
impl Ty {
pub fn to_type_expr(&self) -> TypeExpr {
match self {
Ty::Named(name) => TypeExpr::Named((*name).into()),
Ty::Generic(name) => TypeExpr::Named((*name).into()),
Ty::Any => TypeExpr::Named("any".into()),
Ty::Optional(inner) => {
TypeExpr::Union(vec![inner.to_type_expr(), TypeExpr::Named("nil".into())])
}
Ty::Apply(name, args) => TypeExpr::Applied {
name: (*name).into(),
args: args.iter().map(Ty::to_type_expr).collect(),
},
Ty::Union(members) => TypeExpr::Union(members.iter().map(Ty::to_type_expr).collect()),
Ty::Fn(params, return_type) => TypeExpr::FnType {
params: params.iter().map(Ty::to_type_expr).collect(),
return_type: Box::new(return_type.to_type_expr()),
},
Ty::Shape(fields) => TypeExpr::Shape(
fields
.iter()
.map(|f| ShapeField {
name: f.name.into(),
type_expr: f.ty.to_type_expr(),
optional: f.optional,
})
.collect(),
),
Ty::SchemaOf(name) => TypeExpr::Applied {
name: "Schema".into(),
args: vec![TypeExpr::Named((*name).into())],
},
Ty::Never => TypeExpr::Never,
Ty::LitInt(v) => TypeExpr::LitInt(*v),
Ty::LitString(s) => TypeExpr::LitString((*s).into()),
}
}
pub fn is_any(&self) -> bool {
matches!(self, Ty::Any)
}
}
impl BuiltinSignature {
pub fn required_params(&self) -> usize {
self.params.iter().filter(|p| !p.optional).count()
}
pub fn is_type_param(&self, name: &str) -> bool {
self.type_params.contains(&name)
}
pub fn is_generic(&self) -> bool {
!self.type_params.is_empty()
}
pub fn type_param_names(&self) -> Vec<String> {
self.type_params.iter().map(|s| (*s).to_string()).collect()
}
pub fn param_type_exprs(&self) -> Vec<TypeExpr> {
self.params.iter().map(|p| p.ty.to_type_expr()).collect()
}
pub fn return_type_expr(&self) -> TypeExpr {
self.returns.to_type_expr()
}
pub fn where_clause_strings(&self) -> Vec<(String, String)> {
self.where_clauses
.iter()
.map(|(tp, iface)| ((*tp).to_string(), (*iface).to_string()))
.collect()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BuiltinMetadata {
pub name: &'static str,
pub return_types: &'static [&'static str],
}
pub const TY_ANY: Ty = Ty::Any;
pub const TY_BOOL: Ty = Ty::Named("bool");
pub const TY_BYTES: Ty = Ty::Named("bytes");
pub const TY_CLOSURE: Ty = Ty::Named("closure");
pub const TY_DICT: Ty = Ty::Named("dict");
pub const TY_DURATION: Ty = Ty::Named("duration");
pub const TY_FLOAT: Ty = Ty::Named("float");
pub const TY_INT: Ty = Ty::Named("int");
pub const TY_LIST: Ty = Ty::Named("list");
pub const TY_NEVER: Ty = Ty::Never;
pub const TY_NIL: Ty = Ty::Named("nil");
pub const TY_STRING: Ty = Ty::Named("string");
pub const TY_STRING_OR_NIL: Ty = Ty::Union(&[TY_STRING, TY_NIL]);
pub const TY_INT_OR_NIL: Ty = Ty::Union(&[TY_INT, TY_NIL]);
pub const TY_DICT_OR_NIL: Ty = Ty::Union(&[TY_DICT, TY_NIL]);
pub const TY_BYTES_OR_NIL: Ty = Ty::Union(&[TY_BYTES, TY_NIL]);
pub const TY_NUMBER: Ty = Ty::Union(&[TY_INT, TY_FLOAT]);