From 44d1f4036294db4b5bfb93430f152767ee29d244 Mon Sep 17 00:00:00 2001 From: Arthur Paulino Date: Tue, 12 Sep 2023 15:49:57 -0300 Subject: [PATCH] use an IndexMap to stabilize the order of coprocessors in a Lang --- src/eval/lang.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/eval/lang.rs b/src/eval/lang.rs index 0b948f4eba..672570b30a 100644 --- a/src/eval/lang.rs +++ b/src/eval/lang.rs @@ -1,7 +1,7 @@ -use std::collections::HashMap; use std::fmt::Debug; use std::marker::PhantomData; +use indexmap::IndexMap; use lurk_macros::Coproc; use serde::{Deserialize, Serialize}; @@ -10,6 +10,7 @@ use crate::field::LurkField; use crate::ptr::Ptr; use crate::store::Store; use crate::symbol::Symbol; +use crate::tag::ExprTag; use crate::z_ptr::ZExprPtr; use crate::{self as lurk, lurk_sym_ptr}; @@ -76,10 +77,35 @@ pub enum Coproc { /// exact set of coprocessors to be allowed in the `Lang` struct. /// // TODO: Define a trait for the Hash and parameterize on that also. -#[derive(Debug, Default, Clone, Deserialize, Serialize)] +#[derive(Debug, Default, Clone)] pub struct Lang> { - // A HashMap that stores coprocessors with their associated `Sym` keys. - coprocessors: HashMap)>, + /// An IndexMap that stores coprocessors with their associated `Sym` keys + coprocessors: IndexMap)>, +} + +impl + Serialize> Serialize for Lang { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let vec = self.coprocessors.clone().into_iter().collect::>(); + vec.serialize(serializer) + } +} + +impl<'a, F: LurkField + Deserialize<'a>, C: Coprocessor + Deserialize<'a>> Deserialize<'a> + for Lang +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'a>, + { + use crate::z_ptr::ZPtr; + let vec: Vec<(Symbol, (C, ZPtr))> = Vec::deserialize(deserializer)?; + Ok(Lang { + coprocessors: IndexMap::from_iter(vec), + }) + } } impl> Lang { @@ -127,6 +153,13 @@ impl> Lang { self.coprocessors.insert(name, (cproc.into(), z_ptr)); } + pub fn add_coprocessor_lem, S: Into>(&mut self, name: S, cproc: T) { + let name = name.into(); + // TODO: eliminate this unecessary piece of data + let z_ptr = lurk::z_ptr::ZPtr(ExprTag::Nil, F::ZERO); + self.coprocessors.insert(name, (cproc.into(), z_ptr)); + } + pub fn add_binding>>(&mut self, binding: B, store: &mut Store) { let Binding { name, coproc, _p } = binding.into(); let ptr = store.intern_symbol(&name); @@ -135,7 +168,15 @@ impl> Lang { self.coprocessors.insert(name, (coproc, z_ptr)); } - pub fn coprocessors(&self) -> &HashMap)> { + pub fn add_binding_lem>>(&mut self, binding: B) { + let Binding { name, coproc, _p } = binding.into(); + // TODO: eliminate this unecessary piece of data + let z_ptr = lurk::z_ptr::ZPtr(ExprTag::Nil, F::ZERO); + self.coprocessors.insert(name, (coproc, z_ptr)); + } + + #[inline] + pub fn coprocessors(&self) -> &IndexMap)> { &self.coprocessors } @@ -153,10 +194,22 @@ impl> Lang { maybe_sym.and_then(|sym| self.coprocessors.get(&sym)) } + #[inline] + pub fn lookup_by_sym(&self, sym: &Symbol) -> Option<&C> { + self.coprocessors.get(sym).map(|(c, _)| c) + } + + #[inline] + pub fn get_coprocessor_index(&self, sym: &Symbol) -> Option { + self.coprocessors.get_index_of(sym) + } + + #[inline] pub fn has_coprocessors(&self) -> bool { !self.coprocessors.is_empty() } + #[inline] pub fn is_default(&self) -> bool { !self.has_coprocessors() }