#![warn(missing_docs)]
#![doc = include_str!("../README.md")]
#[cfg(feature = "rlua")]
pub mod rlu;
#[cfg(feature = "mlua")]
pub mod mlu;
mod export_instance;
mod exported_function;
mod teal_multivalue;
mod type_generator;
mod type_representation;
mod type_walker;
use std::{borrow::Cow, collections::HashSet};
pub use exported_function::ExportedFunction;
use serde::{Deserialize, Serialize};
pub use teal_multivalue::{TealMultiValue, TealType};
#[cfg(feature = "derive")]
pub use tealr_derive::ToTypename;
pub use type_generator::{EnumGenerator, Field, NameContainer, RecordGenerator, TypeGenerator};
pub use type_representation::{type_parts_to_str, KindOfType, NamePart, TypeBody, TypeName};
pub use type_walker::{ExtraPage, GlobalInstance, TypeWalker};
#[cfg(feature = "compile")]
pub use tealr_derive::compile_inline_teal;
#[cfg(any(
feature = "embed_compiler_from_local",
feature = "embed_compiler_from_download"
))]
pub use tealr_derive::embed_compiler;
pub fn get_tealr_version() -> &'static str {
env!("CARGO_PKG_VERSION")
}
#[derive(PartialEq, Eq, Hash, Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(
all(feature = "mlua", feature = "derive", not(feature = "rlua")),
derive(crate::mlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(feature = "rlua", feature = "derive", not(feature = "mlua")),
derive(crate::rlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive", not(all(feature = "rlua", feature = "mlua"))),
tealr(tealr_name = crate)
)]
pub struct Name(
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive",not(all(feature = "rlua", feature = "mlua"))),
tealr(remote = String))]
pub Cow<'static, str>,
);
impl core::fmt::Display for Name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl<T: AsRef<str>> From<T> for Name {
fn from(value: T) -> Self {
Name(value.as_ref().to_owned().into())
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(
all(feature = "mlua", feature = "derive", not(feature = "rlua")),
derive(crate::mlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(feature = "rlua", feature = "derive", not(feature = "mlua")),
derive(crate::rlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive", not(all(feature = "rlua", feature = "mlua"))),
tealr(tealr_name = crate)
)]
pub struct SingleType {
pub name: Name,
pub kind: KindOfType,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(
all(feature = "mlua", feature = "derive", not(feature = "rlua")),
derive(crate::mlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(feature = "rlua", feature = "derive", not(feature = "mlua")),
derive(crate::rlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive", not(all(feature = "rlua", feature = "mlua"))),
tealr(tealr_name = crate)
)]
pub struct FunctionParam {
pub param_name: Option<Name>,
pub ty: Type,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(
all(feature = "mlua", feature = "derive", not(feature = "rlua")),
derive(crate::mlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(feature = "rlua", feature = "derive", not(feature = "mlua")),
derive(crate::rlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive", not(all(feature = "rlua", feature = "mlua"))),
tealr(tealr_name = crate)
)]
pub struct FunctionRepresentation {
pub params: Vec<FunctionParam>,
pub returns: Vec<Type>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(
all(feature = "mlua", feature = "derive", not(feature = "rlua")),
derive(crate::mlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(feature = "rlua", feature = "derive", not(feature = "mlua")),
derive(crate::rlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive", not(all(feature = "rlua", feature = "mlua"))),
tealr(tealr_name = crate)
)]
pub struct MapRepresentation {
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive",not(all(feature = "rlua", feature = "mlua"))),
tealr(remote = Type))]
pub key: Box<Type>,
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive",not(all(feature = "rlua", feature = "mlua"))),
tealr(remote = Type))]
pub value: Box<Type>,
}
type NewTypeArray = Vec<Type>;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(
all(feature = "mlua", feature = "derive", not(feature = "rlua")),
derive(crate::mlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(feature = "rlua", feature = "derive", not(feature = "mlua")),
derive(crate::rlu::FromToLua, crate::ToTypename)
)]
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive", not(all(feature = "rlua", feature = "mlua"))),
tealr(tealr_name = crate)
)]
pub enum Type {
Function(FunctionRepresentation),
Single(SingleType),
Map(MapRepresentation),
Or(
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive",not(all(feature = "rlua", feature = "mlua"))),
tealr(remote = NewTypeArray))]
Vec<Type>,
),
Array(
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive",not(all(feature = "rlua", feature = "mlua"))),
tealr(remote = Type))]
Box<Type>,
),
Tuple(
#[cfg_attr(
all(any(feature = "rlua", feature = "mlua"), feature = "derive",not(all(feature = "rlua", feature = "mlua"))),
tealr(remote = NewTypeArray))]
Vec<Type>,
),
}
impl From<Box<Type>> for Type {
fn from(value: Box<Type>) -> Self {
*value
}
}
impl Type {
pub fn new_single(name: impl AsRef<str>, kind: KindOfType) -> Self {
Self::Single(SingleType {
name: name.into(),
kind,
})
}
}
pub trait ToTypename {
#[deprecated]
fn to_old_type_parts() -> Cow<'static, [NamePart]> {
#[allow(deprecated)]
new_type_to_old(Self::to_typename(), false)
}
fn to_typename() -> Type;
fn to_function_param() -> Vec<FunctionParam> {
vec![FunctionParam {
param_name: None,
ty: Self::to_typename(),
}]
}
}
impl<T: ToTypename> TypeName for T {
fn get_type_parts() -> Cow<'static, [NamePart]> {
#[allow(deprecated)]
Self::to_old_type_parts()
}
}
#[deprecated]
pub fn new_type_to_old(a: Type, is_callback: bool) -> Cow<'static, [NamePart]> {
match a {
Type::Single(a) => Cow::Owned(vec![NamePart::Type(TealType {
name: a.name.0,
type_kind: a.kind,
generics: None,
})]),
Type::Array(x) => {
let mut parts = Vec::with_capacity(3);
parts.push(NamePart::symbol("{"));
parts.extend(new_type_to_old(*x, true).iter().cloned());
parts.push(NamePart::symbol("}"));
parts.into()
}
Type::Map(MapRepresentation { key, value }) => {
let mut parts = Vec::with_capacity(5);
parts.push(NamePart::symbol("{"));
parts.extend(new_type_to_old(*key, true).iter().cloned());
parts.push(NamePart::symbol(" : "));
parts.extend(new_type_to_old(*value, true).iter().cloned());
parts.push(NamePart::symbol("}"));
parts.into()
}
Type::Or(x) => {
if x.is_empty() {
eprintln!("An NewType::Or found with empty contents. Skipping");
return Vec::new().into();
}
let mut parts = Vec::with_capacity(x.len());
parts.push(NamePart::symbol("("));
for part in x {
parts.extend(new_type_to_old(part, true).iter().cloned());
parts.push(NamePart::symbol(" | "))
}
parts.pop();
parts.push(NamePart::symbol(")"));
parts.into()
}
Type::Tuple(x) => {
if x.is_empty() {
eprintln!("An NewType::Tuple found with empty contents. Skipping");
return Vec::new().into();
}
let mut parts = Vec::with_capacity(x.len());
parts.push(NamePart::symbol("("));
for part in x {
parts.extend(new_type_to_old(part, true).iter().cloned());
parts.push(NamePart::symbol(" , "))
}
parts.pop();
parts.push(NamePart::symbol(")"));
parts.into()
}
Type::Function(FunctionRepresentation { params, returns }) => {
let mut parts = Vec::with_capacity(params.len() + returns.len());
parts.push(NamePart::symbol("function"));
let generics: HashSet<_> = params
.iter()
.map(|v| &v.ty)
.chain(returns.iter())
.flat_map(get_generics)
.collect();
let generic_amount = generics.len();
if (!is_callback) && generic_amount > 0 {
parts.push(NamePart::Symbol("<".into()));
for generic in generics {
parts.push(NamePart::Type(TealType {
name: generic.0.clone(),
type_kind: KindOfType::Generic,
generics: None,
}));
parts.push(NamePart::symbol(","));
}
parts.pop();
parts.push(NamePart::symbol(">"));
}
parts.push(NamePart::symbol("("));
let has_params = !params.is_empty();
for param in params {
if let Some(name) = param.param_name {
parts.push(NamePart::Symbol(name.0.clone()));
parts.push(NamePart::symbol(":"));
}
parts.extend(new_type_to_old(param.ty, true).iter().cloned());
parts.push(NamePart::symbol(" , "));
}
if has_params {
parts.pop();
}
parts.push(NamePart::symbol(")"));
if !returns.is_empty() {
parts.push(NamePart::symbol(":("));
for ret in returns {
parts.extend(new_type_to_old(ret, true).iter().cloned());
parts.push(NamePart::symbol(" , "))
}
parts.pop();
parts.push(NamePart::symbol(")"));
}
Cow::Owned(parts)
}
}
}
pub fn get_generics(to_check: &Type) -> HashSet<&Name> {
match to_check {
Type::Function(FunctionRepresentation { params, returns }) => params
.iter()
.map(|v| &v.ty)
.chain(returns.iter())
.flat_map(get_generics)
.collect(),
Type::Array(x) => get_generics(x.as_ref()),
Type::Single(x) => {
let mut set = HashSet::new();
if x.kind == KindOfType::Generic {
set.insert(&x.name);
}
set
}
Type::Or(x) | Type::Tuple(x) => x.iter().flat_map(get_generics).collect(),
Type::Map(MapRepresentation { key, value }) => {
let mut generics = get_generics(key);
generics.extend(get_generics(value));
generics
}
}
}