serde nonsense

This commit is contained in:
Parker TenBroeck 2026-01-11 16:35:17 -05:00
parent 90d96f0738
commit c06a0a0147
4 changed files with 176 additions and 81 deletions

View file

@ -2,51 +2,60 @@ use std::collections::HashSet;
use super::*; use super::*;
use crate::{delta_lower, gamma_upper, loader::{ use crate::{delta_lower, dual_struct_serde, gamma_upper, loader::{
Context, INITIAL_STACK, INITIAL_STATE, Spanned, ast::{self, Symbol as Sym}, log::LogSink Context, INITIAL_STACK, INITIAL_STATE, Spanned, ast::{self, Symbol as Sym}, log::LogSink
}, sigma_upper}; }, sigma_upper};
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] dual_struct_serde! {
#[cfg_attr(feature = "serde", derive(serde::Serialize))] #[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct TransitionFrom<'a> { pub struct TransitionFrom<'a> {
pub state: State<'a>, #[serde(borrow)]
pub letter: Option<Letter<'a>>, pub state: State<'a>,
pub symbol: Symbol<'a>, #[serde(borrow)]
pub letter: Option<Letter<'a>>,
#[serde(borrow)]
pub symbol: Symbol<'a>,
}
} }
#[derive(Debug, PartialEq, Eq, Clone, Hash)] dual_struct_serde! {
#[cfg_attr(feature = "serde", derive(serde::Serialize))] #[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct TransitionTo<'a> { pub struct TransitionTo<'a> {
pub state: State<'a>, #[serde(borrow)]
pub stack: Vec<Symbol<'a>>, pub state: State<'a>,
#[serde(borrow)]
pub stack: Vec<Symbol<'a>>,
pub transition: Span, pub transition: Span,
pub function: Span, pub function: Span,
}
} }
#[derive(Clone, Debug)] dual_struct_serde! { {#[serde_with::serde_as]}
#[allow(unused)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", serde_with::serde_as)] pub struct Pda<'a> {
#[cfg_attr(feature = "serde", derive(serde::Serialize))] #[serde(borrow)]
pub struct Pda<'a> { pub initial_state: State<'a>,
pub initial_state: State<'a>, #[serde(borrow)]
pub initial_stack: Symbol<'a>, pub initial_stack: Symbol<'a>,
pub states: HashMap<State<'a>, StateInfo>, #[serde(borrow)]
pub symbols: HashMap<Symbol<'a>, SymbolInfo>, pub states: HashMap<State<'a>, StateInfo>,
pub alphabet: HashMap<Letter<'a>, LetterInfo>, #[serde(borrow)]
pub symbols: HashMap<Symbol<'a>, SymbolInfo>,
#[serde(borrow)]
pub alphabet: HashMap<Letter<'a>, LetterInfo>,
pub final_states: Option<HashMap<State<'a>, StateInfo>>, #[serde(borrow)]
pub final_states: Option<HashMap<State<'a>, StateInfo>>,
#[cfg(feature = "serde")] #[serde(borrow)]
#[serde_as(as = "serde_with::Seq<(_, _)>")] #[serde_as(as = "serde_with::Seq<(_, _)>")]
pub transitions: HashMap<TransitionFrom<'a>, HashSet<TransitionTo<'a>>>, pub transitions: HashMap<TransitionFrom<'a>, HashSet<TransitionTo<'a>>>,
}
#[cfg(not(feature = "serde"))]
pub transitions: HashMap<TransitionFrom<'a>, HashSet<TransitionTo<'a>>>,
} }
impl<'a> Pda<'a> { impl<'a> Pda<'a> {
pub fn parse( pub fn compile(
items: impl Iterator<Item = Spanned<ast::TopLevel<'a>>>, items: impl Iterator<Item = Spanned<ast::TopLevel<'a>>>,
ctx: &mut Context<'a>, ctx: &mut Context<'a>,
options: Options, options: Options,

View file

@ -2,57 +2,65 @@ use std::collections::HashSet;
use super::*; use super::*;
use crate::{delta_lower, gamma_upper, loader::{ use crate::{delta_lower, dual_struct_serde, gamma_upper, loader::{
BLANK_SYMBOL, Context, Spanned, ast::{self, Symbol as Sym}, log::LogSink BLANK_SYMBOL, Context, Spanned, ast::{self, Symbol as Sym}, log::LogSink
}}; }};
dual_struct_serde! {
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct TransitionFrom<'a> {
pub struct TransitionFrom<'a> { #[serde(borrow)]
pub state: State<'a>, pub state: State<'a>,
pub symbol: Symbol<'a>, #[serde(borrow)]
pub symbol: Symbol<'a>,
}
} }
#[derive(Debug, PartialEq, Eq, Clone, Hash)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Direction { pub enum Direction {
Left, Left,
Right, Right,
None, None,
} }
#[derive(Debug, PartialEq, Eq, Clone, Hash)] dual_struct_serde! {
#[cfg_attr(feature = "serde", derive(serde::Serialize))] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct TransitionTo<'a> { pub struct TransitionTo<'a> {
pub state: State<'a>, #[serde(borrow)]
pub symbol: Symbol<'a>, pub state: State<'a>,
pub direction: Direction, #[serde(borrow)]
pub symbol: Symbol<'a>,
pub direction: Direction,
pub transition: Span, pub transition: Span,
pub function: Span, pub function: Span,
}
} }
#[derive(Clone, Debug)] dual_struct_serde! {{#[serde_with::serde_as]}
#[allow(unused)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", serde_with::serde_as)] pub struct Tm<'a> {
#[cfg_attr(feature = "serde", derive(serde::Serialize))] #[serde(borrow)]
pub struct Tm<'a> { pub initial_state: State<'a>,
pub initial_state: State<'a>, #[serde(borrow)]
pub initial_tape: Symbol<'a>, pub initial_tape: Symbol<'a>,
pub states: HashMap<State<'a>, StateInfo>, #[serde(borrow)]
pub symbols: HashMap<Symbol<'a>, SymbolInfo>, pub states: HashMap<State<'a>, StateInfo>,
#[serde(borrow)]
pub symbols: HashMap<Symbol<'a>, SymbolInfo>,
pub final_states: HashMap<State<'a>, StateInfo>, #[serde(borrow)]
pub final_states: HashMap<State<'a>, StateInfo>,
#[cfg(feature = "serde")]
#[serde_as(as = "serde_with::Seq<(_, _)>")] #[serde(borrow)]
pub transitions: HashMap<TransitionFrom<'a>, HashSet<TransitionTo<'a>>>, #[serde_as(as = "serde_with::Seq<(_, _)>")]
#[cfg(not(feature = "serde"))] pub transitions: HashMap<TransitionFrom<'a>, HashSet<TransitionTo<'a>>>,
pub transitions: HashMap<TransitionFrom<'a>, HashSet<TransitionTo<'a>>>, }
} }
impl<'a> Tm<'a> { impl<'a> Tm<'a> {
pub fn parse( pub fn compile(
items: impl Iterator<Item = Spanned<ast::TopLevel<'a>>>, items: impl Iterator<Item = Spanned<ast::TopLevel<'a>>>,
ctx: &mut Context<'a>, ctx: &mut Context<'a>,
options: Options, options: Options,

View file

@ -1,7 +1,6 @@
pub mod automatan; pub mod automatan;
pub mod loader; pub mod loader;
#[macro_export] #[macro_export]
macro_rules! dual_struct_serde { macro_rules! dual_struct_serde {
($({$(#[$serde_specific:meta])*})? ($({$(#[$serde_specific:meta])*})?
@ -33,4 +32,83 @@ macro_rules! dual_struct_serde {
),* ),*
} }
}; };
} }
#[macro_export]
macro_rules! dual_enum_serde {
(
$( {$(#[$serde_specific:meta])*} )?
$(#[$enum_meta:meta])*
$vis:vis enum $Name:ident $(<$($gen:tt),*>)?
{
$(
$(#[$variant_meta:meta])*
$Variant:ident
$(
// Tuple variant: Variant(T1, T2, ...)
( $(
$(#[$tfield_meta:meta])*
$tfield_ty:ty
),* $(,)? )
)?
$(
// Struct variant: Variant { a: T, b: U, ... }
{ $(
$(#[$sfield_meta:meta])*
$sfield_vis:vis $sfield_name:ident : $sfield_ty:ty
),* $(,)? }
)?
),* $(,)?
}
) => {
#[cfg(feature = "serde")]
$(#[$enum_meta])*
#[derive(serde::Serialize, serde::Deserialize)]
$( $(#[$serde_specific])* )?
$vis enum $Name $(<$($gen),*>)? {
$(
$(#[$variant_meta])*
$Variant
$(
(
$(
$(#[$tfield_meta])*
$tfield_ty
),*
)
)?
$(
{
$(
$(#[$sfield_meta])*
$sfield_vis $sfield_name: $sfield_ty
),*
}
)?
),*
}
#[cfg(not(feature = "serde"))]
$(#[$enum_meta])*
$vis enum $Name $(<$($gen),*>)? {
$(
// strip variant + field attrs in non-serde version
$Variant
$(
(
$(
$tfield_ty
),*
)
)?
$(
{
$(
$sfield_vis $sfield_name: $sfield_ty
),*
}
)?
),*
}
};
}

View file

@ -1,9 +1,8 @@
use crate::{ use crate::{
automatan::*, automatan::*, dual_enum_serde, dual_struct_serde, loader::{
loader::{
ast::TopLevel, ast::TopLevel,
log::{LogEntry, LogSink}, log::{LogEntry, LogSink},
}, }
}; };
pub mod ast; pub mod ast;
@ -120,13 +119,14 @@ impl<'a> Context<'a> {
} }
} }
#[cfg_attr(feature = "serde", derive(serde::Serialize))] dual_enum_serde!{
#[cfg_attr(feature = "serde", serde(tag = "type"))] {#[serde(tag = "type")] #[serde(rename_all = "snake_case")]}
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] #[derive(Clone, Debug)]
pub enum Machine<'a> { pub enum Machine<'a> {
Fa(fa::Fa<'a>), Fa(#[serde(borrow)] fa::Fa<'a>),
Pda(pda::Pda<'a>), Pda(#[serde(borrow)] pda::Pda<'a>),
Tm(tm::Tm<'a>), Tm(#[serde(borrow)] tm::Tm<'a>),
}
} }
pub fn parse_universal<'a>(ctx: &mut Context<'a>) -> Option<Machine<'a>> { pub fn parse_universal<'a>(ctx: &mut Context<'a>) -> Option<Machine<'a>> {
@ -194,9 +194,9 @@ pub fn parse_universal<'a>(ctx: &mut Context<'a>) -> Option<Machine<'a>> {
Some(match parse_type(items.next(), ctx)? { Some(match parse_type(items.next(), ctx)? {
Type::Dfa => Machine::Fa(fa::Fa::compile(items, ctx, D)?), Type::Dfa => Machine::Fa(fa::Fa::compile(items, ctx, D)?),
Type::Nfa => Machine::Fa(fa::Fa::compile(items, ctx, N)?), Type::Nfa => Machine::Fa(fa::Fa::compile(items, ctx, N)?),
Type::Dpda => Machine::Pda(pda::Pda::parse(items, ctx, D)?), Type::Dpda => Machine::Pda(pda::Pda::compile(items, ctx, D)?),
Type::Npda => Machine::Pda(pda::Pda::parse(items, ctx, N)?), Type::Npda => Machine::Pda(pda::Pda::compile(items, ctx, N)?),
Type::Tm => Machine::Tm(tm::Tm::parse(items, ctx, D)?), Type::Tm => Machine::Tm(tm::Tm::compile(items, ctx, D)?),
Type::Ntm => Machine::Tm(tm::Tm::parse(items, ctx, N)?), Type::Ntm => Machine::Tm(tm::Tm::compile(items, ctx, N)?),
}) })
} }