From a0ec6928d8dc464dcb5de313379f3cdac7ec729b Mon Sep 17 00:00:00 2001 From: dan <70999565+belovdv@users.noreply.github.com> Date: Thu, 3 Sep 2026 16:07:53 +0300 Subject: [PATCH] [rust] reimplement serialization --- rust/Cargo.lock | 13 +- rust/Cargo.toml | 1 - rust/lira/Cargo.toml | 1 - rust/lira/src/arch.rs | 2 - rust/lira/src/arch_ser_yaml.rs | 483 ++------------------------------- rust/lira/src/ir.rs | 21 +- 6 files changed, 47 insertions(+), 474 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 5e47705..6ce5eab 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -18,9 +18,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] @@ -581,7 +581,6 @@ dependencies = [ "regex", "serde", "serde_yaml", - "yaml-rust", ] [[package]] @@ -830,9 +829,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.4" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -842,9 +841,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 43c02f4..1523fd5 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -12,7 +12,6 @@ ahash = "0.8.12" regex = "1.12.3" serde = "1.0.228" serde_yaml = "0.8" -yaml-rust = "0.4" [profile.work] inherits = "dev" diff --git a/rust/lira/Cargo.toml b/rust/lira/Cargo.toml index 6309bbb..c17649b 100644 --- a/rust/lira/Cargo.toml +++ b/rust/lira/Cargo.toml @@ -10,4 +10,3 @@ ahash = { workspace = true, features = ["serde"] } regex = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_yaml = { workspace = true } -yaml-rust = { workspace = true } diff --git a/rust/lira/src/arch.rs b/rust/lira/src/arch.rs index 0f0ed32..a519b56 100644 --- a/rust/lira/src/arch.rs +++ b/rust/lira/src/arch.rs @@ -23,7 +23,6 @@ pub struct Operation { #[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] pub struct Register { pub name: String, - #[serde(default)] pub attributes: Vec, } @@ -106,7 +105,6 @@ pub struct Instruction { pub operand_sizes: Vec, pub operand_names: Vec, pub encoding: InstructionEncoding, - #[serde(skip)] pub semantic: StatementSeq, } diff --git a/rust/lira/src/arch_ser_yaml.rs b/rust/lira/src/arch_ser_yaml.rs index fe2ec4c..f9a5b23 100644 --- a/rust/lira/src/arch_ser_yaml.rs +++ b/rust/lira/src/arch_ser_yaml.rs @@ -1,471 +1,30 @@ use std::path::Path; -use regex::Regex; -use serde::Deserialize; -use yaml_rust::yaml::Hash; -use yaml_rust::{Yaml, YamlEmitter}; - -use crate::*; - -fn blockify_yaml(yaml: &str) -> String { - let re = Regex::new(r#"(?m)^(\s*)(seq|semantic):\s*"(.*)"$"#).unwrap(); - let mut result = yaml.to_string(); - let mut offset: isize = 0; - - let caps: Vec<_> = re.captures_iter(yaml).collect(); - for cap in caps { - let indent = cap.get(1).unwrap().as_str(); - let key = cap.get(2).unwrap().as_str(); - let body = cap.get(3).unwrap().as_str().replace("\\n", "\n"); - let body_indent = format!("{} ", indent); - - let mut replacement = format!("{}{}: |\n", indent, key); - for line in body.lines() { - replacement.push_str(&body_indent); - replacement.push_str(line); - replacement.push('\n'); - } - if body.ends_with('\n') { - replacement.push('\n'); - } - - let cap_start = cap.get(0).unwrap().start() as isize + offset; - let cap_end = cap.get(0).unwrap().end() as isize + offset; - let old_len = (cap_end - cap_start) as usize; - result.replace_range(cap_start as usize..cap_end as usize, &replacement); - offset += replacement.len() as isize - old_len as isize; +impl crate::Arch { + pub fn write_yaml(&self, path: impl AsRef) -> anyhow::Result<()> { + Ok(std::fs::write(path, expand(&serde_yaml::to_string(self)?))?) } - result -} - -fn arch_to_yaml(arch: &Arch) -> anyhow::Result { - let snippets: Vec = arch - .snippets - .iter() - .map(|s| { - let mut map = Hash::new(); - map.insert(Yaml::String("name".into()), Yaml::String(s.name.clone())); - map.insert(Yaml::String("seq".into()), Yaml::String(s.seq.to_string())); - Yaml::Hash(map) - }) - .collect(); - - let instructions: Vec = arch - .instructions - .iter() - .map(|i| { - let mut map = Hash::new(); - map.insert(Yaml::String("name".into()), Yaml::String(i.name.clone())); - map.insert( - Yaml::String("attributes".into()), - Yaml::Array( - i.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - map.insert( - Yaml::String("operand_sizes".into()), - Yaml::Array( - i.operand_sizes - .iter() - .map(|&sz| Yaml::Integer(sz as i64)) - .collect(), - ), - ); - map.insert( - Yaml::String("operand_names".into()), - Yaml::Array( - i.operand_names - .iter() - .map(|n| Yaml::String(n.clone())) - .collect(), - ), - ); - { - let mut enc_map = Hash::new(); - enc_map.insert( - Yaml::String("encoded_size".into()), - Yaml::Integer(i.encoding.encoded_size as i64), - ); - enc_map.insert( - Yaml::String("const_encoding_part".into()), - Yaml::Integer(i.encoding.const_encoding_part as i64), - ); - enc_map.insert( - Yaml::String("const_mask".into()), - Yaml::Integer(i.encoding.const_mask as i64), - ); - enc_map.insert( - Yaml::String("decode".into()), - Yaml::Array( - i.encoding - .decode - .iter() - .map(|d| Yaml::String(d.clone())) - .collect(), - ), - ); - enc_map.insert( - Yaml::String("encode".into()), - Yaml::String(i.encoding.encode.clone()), - ); - enc_map.insert( - Yaml::String("constraint_decode".into()), - Yaml::String(i.encoding.constraint_decode.clone()), - ); - enc_map.insert( - Yaml::String("constraint_encode".into()), - Yaml::String(i.encoding.constraint_encode.clone()), - ); - map.insert(Yaml::String("encoding".into()), Yaml::Hash(enc_map)); - } - map.insert( - Yaml::String("semantic".into()), - Yaml::String(i.semantic.to_string()), - ); - Yaml::Hash(map) - }) - .collect(); - - let register_files: Vec = arch - .register_files - .iter() - .map(|rf| { - let mut map = Hash::new(); - map.insert(Yaml::String("name".into()), Yaml::String(rf.name.clone())); - map.insert( - Yaml::String("attributes".into()), - Yaml::Array( - rf.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - { - let mut shape = Hash::new(); - shape.insert( - Yaml::String("lanes_base".into()), - Yaml::Integer(rf.reg_size.lanes_base as i64), - ); - shape.insert( - Yaml::String("lanes_mult".into()), - match &rf.reg_size.lanes_mult { - Some(m) => Yaml::String(m.clone()), - None => Yaml::Null, - }, - ); - map.insert(Yaml::String("reg_size".into()), Yaml::Hash(shape)); - } - map.insert( - Yaml::String("regs".into()), - Yaml::Array( - rf.regs - .iter() - .map(|r| { - let mut rm = Hash::new(); - rm.insert(Yaml::String("name".into()), Yaml::String(r.name.clone())); - rm.insert( - Yaml::String("attributes".into()), - Yaml::Array( - r.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - Yaml::Hash(rm) - }) - .collect(), - ), - ); - Yaml::Hash(map) - }) - .collect(); - - let env_funcs: Vec = arch - .environment_functions - .iter() - .map(|ef| { - let mut map = Hash::new(); - map.insert(Yaml::String("name".into()), Yaml::String(ef.name.clone())); - map.insert( - Yaml::String("attributes".into()), - Yaml::Array( - ef.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - map.insert( - Yaml::String("inputs".into()), - Yaml::Array( - ef.inputs - .iter() - .map(|&sz| Yaml::Integer(sz as i64)) - .collect(), - ), - ); - map.insert( - Yaml::String("outputs".into()), - Yaml::Array( - ef.outputs - .iter() - .map(|&sz| Yaml::Integer(sz as i64)) - .collect(), - ), - ); - Yaml::Hash(map) - }) - .collect(); - - let operations: Vec = arch - .operations - .iter() - .map(|op| { - let mut map = Hash::new(); - map.insert(Yaml::String("name".into()), Yaml::String(op.name.clone())); - map.insert( - Yaml::String("attributes".into()), - Yaml::Array( - op.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - map.insert( - Yaml::String("inputs".into()), - Yaml::Array( - op.inputs - .iter() - .map(|&sz| Yaml::Integer(sz as i64)) - .collect(), - ), - ); - map.insert( - Yaml::String("outputs".into()), - Yaml::Array( - op.outputs - .iter() - .map(|&sz| Yaml::Integer(sz as i64)) - .collect(), - ), - ); - if let Some(ref base) = op.semantic_base { - map.insert( - Yaml::String("semantic_base".into()), - Yaml::String(base.clone()), - ); - } else { - map.insert(Yaml::String("semantic_base".into()), Yaml::Null); - } - if let Some(ref func) = op.semantic_func { - map.insert( - Yaml::String("semantic_func".into()), - Yaml::String(func.clone()), - ); - } else { - map.insert(Yaml::String("semantic_func".into()), Yaml::Null); - } - map.insert(Yaml::String("semantic_func_128".into()), Yaml::Null); - map.insert(Yaml::String("semantic_table".into()), Yaml::Null); - Yaml::Hash(map) - }) - .collect(); - - let system_registers: Vec = arch - .system_registers - .iter() - .map(|sr| { - let mut map = Hash::new(); - map.insert(Yaml::String("name".into()), Yaml::String(sr.name.clone())); - map.insert( - Yaml::String("attributes".into()), - Yaml::Array( - sr.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - map.insert(Yaml::String("size".into()), Yaml::Integer(sr.size as i64)); - map.insert( - Yaml::String("fields".into()), - Yaml::Array( - sr.fields - .iter() - .map(|f| { - let mut fm = Hash::new(); - fm.insert(Yaml::String("name".into()), Yaml::String(f.name.clone())); - fm.insert( - Yaml::String("attributes".into()), - Yaml::Array( - f.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - fm.insert(Yaml::String("lsb".into()), Yaml::Integer(f.lsb as i64)); - fm.insert(Yaml::String("msb".into()), Yaml::Integer(f.msb as i64)); - Yaml::Hash(fm) - }) - .collect(), - ), - ); - Yaml::Hash(map) - }) - .collect(); - - let tables_int: Vec = arch - .tables_int - .iter() - .map(|t| { - let mut map = Hash::new(); - map.insert(Yaml::String("name".into()), Yaml::String(t.name.clone())); - map.insert( - Yaml::String("attributes".into()), - Yaml::Array( - t.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - map.insert( - Yaml::String("values".into()), - Yaml::Array(t.values.iter().map(|&v| Yaml::Integer(v as i64)).collect()), - ); - Yaml::Hash(map) - }) - .collect(); - - let mut root = Hash::new(); - root.insert(Yaml::String("name".into()), Yaml::String(arch.name.clone())); - root.insert( - Yaml::String("attributes".into()), - Yaml::Array( - arch.attributes - .iter() - .map(|a| Yaml::String(a.clone())) - .collect(), - ), - ); - root.insert( - Yaml::String("register_files".into()), - Yaml::Array(register_files), - ); - root.insert( - Yaml::String("system_registers".into()), - Yaml::Array(system_registers), - ); - root.insert( - Yaml::String("environment_functions".into()), - Yaml::Array(env_funcs), - ); - root.insert(Yaml::String("tables_int".into()), Yaml::Array(tables_int)); - root.insert(Yaml::String("operations".into()), Yaml::Array(operations)); - root.insert(Yaml::String("snippets".into()), Yaml::Array(snippets)); - root.insert( - Yaml::String("instructions".into()), - Yaml::Array(instructions), - ); - - let doc = Yaml::Hash(root); - let mut out = String::new(); - let mut emitter = YamlEmitter::new(&mut out); - emitter.dump(&doc)?; - - Ok(out) -} - -#[derive(Debug, Clone, Deserialize)] -struct SerializableSnippet { - name: String, - seq: String, -} - -#[derive(Debug, Clone, Deserialize)] -struct SerializableInstruction { - name: String, - attributes: Vec, - operand_sizes: Vec, - operand_names: Vec, - encoding: InstructionEncoding, - semantic: String, -} - -#[derive(Debug, Clone, Deserialize)] -struct SerializableArch { - name: String, - attributes: Vec, - register_files: Vec, - system_registers: Vec, - environment_functions: Vec, - tables_int: Vec, - operations: Vec, - snippets: Vec, - instructions: Vec, -} - -impl SerializableArch { - fn into_arch(self) -> anyhow::Result { - let snippets = self - .snippets - .into_iter() - .map(|s| { - Ok(Snippet { - name: s.name, - seq: StatementSeq::parse(&s.seq)?, - }) - }) - .collect::>>()?; - - let instructions = self - .instructions - .into_iter() - .map(|i| { - Ok(Instruction { - name: i.name, - attributes: i.attributes, - operand_sizes: i.operand_sizes, - operand_names: i.operand_names, - encoding: i.encoding, - semantic: StatementSeq::parse(&i.semantic)?, - }) - }) - .collect::>>()?; - - Ok(Arch { - name: self.name, - attributes: self.attributes, - register_files: self.register_files, - system_registers: self.system_registers, - environment_functions: self.environment_functions, - tables_int: self.tables_int, - operations: self.operations, - snippets, - instructions, - }) + pub fn read_yaml(path: impl AsRef) -> anyhow::Result { + Ok(serde_yaml::from_str(&std::fs::read_to_string(path)?)?) } } -impl Arch { - pub fn write_yaml(&self, path: impl AsRef) -> anyhow::Result<()> { - let yaml = arch_to_yaml(self)?; - let yaml = blockify_yaml(&yaml); - std::fs::write(path, yaml)?; - Ok(()) - } - - pub fn read_yaml(path: impl AsRef) -> anyhow::Result { - let content = std::fs::read_to_string(path)?; - let serializable: SerializableArch = serde_yaml::from_str(&content)?; - serializable.into_arch() +// Make output easier to read +fn expand(yaml: &str) -> String { + use std::fmt::Write; + let mut result = String::new(); + for line in yaml.lines() { + let l = line.trim_start(); + if let Some(start) = ["seq:", "semantic:"].iter().find(|s| l.starts_with(*s)) { + let prefix = &line[..line.len() - l.len()]; + writeln!(result, "{prefix}{start} |").unwrap(); + for part in l[start.len() + 2..l.len() - 3].split("\\n") { + writeln!(result, "{prefix} {part}").unwrap(); + } + } else { + writeln!(result, "{line}").unwrap(); + } } + result } diff --git a/rust/lira/src/ir.rs b/rust/lira/src/ir.rs index def5ce3..ac24f41 100644 --- a/rust/lira/src/ir.rs +++ b/rust/lira/src/ir.rs @@ -19,7 +19,7 @@ pub struct Statement { pub inputs: Vec, } -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct StatementSeq { stmts: Vec, stmts_index: AHashMap, @@ -82,3 +82,22 @@ impl Deref for StatementSeq { &self.stmts } } + +impl Serialize for StatementSeq { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'de> Deserialize<'de> for StatementSeq { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + StatementSeq::parse(&s).map_err(serde::de::Error::custom) + } +}