pub mod error;
pub mod expr;
pub mod item;
pub mod stmt;
pub mod ty;
use std::{collections::HashSet, sync::Arc};
pub use error::TranspileError;
use proc_macro2::TokenStream;
use serde::Deserialize;
pub use ty::*;
use crate::ast::Expr;
type FallbackExprHandler = Arc<
dyn for<'de> Fn(
&Expr<'de>,
&Transpiler,
&mut TranspileContext,
&mut TokenStream,
) -> Result<(), TranspileError>
+ Send
+ Sync,
>;
#[derive(Debug, Clone, Default)]
pub struct TranspileContext {
member_vars: HashSet<String>,
scope_stack: Vec<HashSet<String>>,
}
impl TranspileContext {
pub fn new() -> Self {
Self::default()
}
pub fn with_members(member_names: impl IntoIterator<Item = String>) -> Self {
Self {
member_vars: member_names.into_iter().collect(),
scope_stack: Vec::new(),
}
}
pub fn add_member(&mut self, name: String) {
self.member_vars.insert(name);
}
pub fn push_scope(&mut self) {
self.scope_stack.push(HashSet::new());
}
pub fn pop_scope(&mut self) {
self.scope_stack.pop();
}
pub fn declare_local(&mut self, name: String) {
if let Some(scope) = self.scope_stack.last_mut() {
scope.insert(name);
}
}
pub fn is_local(&self, name: &str) -> bool {
self.scope_stack.iter().any(|scope| scope.contains(name))
}
pub fn is_member(&self, name: &str) -> bool {
self.member_vars.contains(name)
}
pub fn needs_self_prefix(&self, name: &str) -> bool {
self.is_member(name) && !self.is_local(name)
}
}
#[derive(Default, Clone, Deserialize)]
pub struct Transpiler {
#[serde(default)]
pub skip_types: HashSet<String>,
#[serde(default)]
pub ty_mapper: TypeMapper,
#[serde(default)]
pub enum_default_variant: bool,
#[serde(skip)]
pub fallback_expr_handler: Option<FallbackExprHandler>,
}
impl std::fmt::Debug for Transpiler {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Transpiler")
.field("skip_types", &self.skip_types)
.field("ty_mapper", &self.ty_mapper)
.field("enum_default_variant", &self.enum_default_variant)
.field(
"fallback_expr_handler",
&self.fallback_expr_handler.as_ref().map(|_| "<closure>"),
)
.finish()
}
}
pub trait Transpile {
fn transpile(
&self,
transpiler: &Transpiler,
ctx: &mut TranspileContext,
tokens: &mut TokenStream,
) -> Result<(), TranspileError>;
fn transpile_token_stream(
&self,
transpiler: &Transpiler,
ctx: &mut TranspileContext,
) -> Result<TokenStream, TranspileError> {
let mut tokens = TokenStream::new();
self.transpile(transpiler, ctx, &mut tokens)?;
Ok(tokens)
}
fn transpile_into_token_stream(
self,
transpiler: &Transpiler,
ctx: &mut TranspileContext,
) -> Result<TokenStream, TranspileError>
where
Self: Sized,
{
self.transpile_token_stream(transpiler, ctx)
}
}