From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_transmute/src/layout/dfa.rs | 184 +++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 compiler/rustc_transmute/src/layout/dfa.rs (limited to 'compiler/rustc_transmute/src/layout/dfa.rs') diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs new file mode 100644 index 000000000..b60ea6e7a --- /dev/null +++ b/compiler/rustc_transmute/src/layout/dfa.rs @@ -0,0 +1,184 @@ +use super::{nfa, Byte, Nfa, Ref}; +use crate::Map; +use std::fmt; +use std::sync::atomic::{AtomicU32, Ordering}; + +#[derive(PartialEq, Clone, Debug)] +pub(crate) struct Dfa +where + R: Ref, +{ + pub(crate) transitions: Map>, + pub(crate) start: State, + pub(crate) accepting: State, +} + +#[derive(PartialEq, Clone, Debug)] +pub(crate) struct Transitions +where + R: Ref, +{ + byte_transitions: Map, + ref_transitions: Map, +} + +impl Default for Transitions +where + R: Ref, +{ + fn default() -> Self { + Self { byte_transitions: Map::default(), ref_transitions: Map::default() } + } +} + +impl Transitions +where + R: Ref, +{ + fn insert(&mut self, transition: Transition, state: State) { + match transition { + Transition::Byte(b) => { + self.byte_transitions.insert(b, state); + } + Transition::Ref(r) => { + self.ref_transitions.insert(r, state); + } + } + } +} + +/// The states in a `Nfa` represent byte offsets. +#[derive(Hash, Eq, PartialEq, PartialOrd, Ord, Copy, Clone)] +pub(crate) struct State(u32); + +#[derive(Hash, Eq, PartialEq, Clone, Copy)] +pub(crate) enum Transition +where + R: Ref, +{ + Byte(Byte), + Ref(R), +} + +impl fmt::Debug for State { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "S_{}", self.0) + } +} + +impl fmt::Debug for Transition +where + R: Ref, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self { + Self::Byte(b) => b.fmt(f), + Self::Ref(r) => r.fmt(f), + } + } +} + +impl Dfa +where + R: Ref, +{ + pub(crate) fn unit() -> Self { + let transitions: Map> = Map::default(); + let start = State::new(); + let accepting = start; + + Self { transitions, start, accepting } + } + + #[cfg(test)] + pub(crate) fn bool() -> Self { + let mut transitions: Map> = Map::default(); + let start = State::new(); + let accepting = State::new(); + + transitions.entry(start).or_default().insert(Transition::Byte(Byte::Init(0x00)), accepting); + + transitions.entry(start).or_default().insert(Transition::Byte(Byte::Init(0x01)), accepting); + + Self { transitions, start, accepting } + } + + #[instrument(level = "debug")] + #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))] + pub(crate) fn from_nfa(nfa: Nfa) -> Self { + let Nfa { transitions: nfa_transitions, start: nfa_start, accepting: nfa_accepting } = nfa; + + let mut dfa_transitions: Map> = Map::default(); + let mut nfa_to_dfa: Map = Map::default(); + let dfa_start = State::new(); + nfa_to_dfa.insert(nfa_start, dfa_start); + + let mut queue = vec![(nfa_start, dfa_start)]; + + while let Some((nfa_state, dfa_state)) = queue.pop() { + if nfa_state == nfa_accepting { + continue; + } + + for (nfa_transition, next_nfa_states) in nfa_transitions[&nfa_state].iter() { + let dfa_transitions = + dfa_transitions.entry(dfa_state).or_insert_with(Default::default); + + let mapped_state = next_nfa_states.iter().find_map(|x| nfa_to_dfa.get(x).copied()); + + let next_dfa_state = match nfa_transition { + &nfa::Transition::Byte(b) => *dfa_transitions + .byte_transitions + .entry(b) + .or_insert_with(|| mapped_state.unwrap_or_else(State::new)), + &nfa::Transition::Ref(r) => *dfa_transitions + .ref_transitions + .entry(r) + .or_insert_with(|| mapped_state.unwrap_or_else(State::new)), + }; + + for &next_nfa_state in next_nfa_states { + nfa_to_dfa.entry(next_nfa_state).or_insert_with(|| { + queue.push((next_nfa_state, next_dfa_state)); + next_dfa_state + }); + } + } + } + + let dfa_accepting = nfa_to_dfa[&nfa_accepting]; + + Self { transitions: dfa_transitions, start: dfa_start, accepting: dfa_accepting } + } + + pub(crate) fn bytes_from(&self, start: State) -> Option<&Map> { + Some(&self.transitions.get(&start)?.byte_transitions) + } + + pub(crate) fn byte_from(&self, start: State, byte: Byte) -> Option { + self.transitions.get(&start)?.byte_transitions.get(&byte).copied() + } + + pub(crate) fn refs_from(&self, start: State) -> Option<&Map> { + Some(&self.transitions.get(&start)?.ref_transitions) + } +} + +impl State { + pub(crate) fn new() -> Self { + static COUNTER: AtomicU32 = AtomicU32::new(0); + Self(COUNTER.fetch_add(1, Ordering::SeqCst)) + } +} + +impl From> for Transition +where + R: Ref, +{ + fn from(nfa_transition: nfa::Transition) -> Self { + match nfa_transition { + nfa::Transition::Byte(byte) => Transition::Byte(byte), + nfa::Transition::Ref(r) => Transition::Ref(r), + } + } +} -- cgit v1.2.3