mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-04-20 03:03:25 -04:00
Formatting of machines inside modules.
This commit is contained in:
@@ -162,9 +162,7 @@ mod tests {
|
||||
env!("CARGO_MANIFEST_DIR")
|
||||
));
|
||||
let file_name = base_path.join(path);
|
||||
let expected = fs::read_to_string(file_name)
|
||||
.unwrap()
|
||||
.replace("machine Main", "machine ::Main");
|
||||
let expected = fs::read_to_string(file_name).unwrap();
|
||||
|
||||
// remove the batch comments from the expected output before compiling
|
||||
let input = expected
|
||||
|
||||
@@ -13,4 +13,7 @@ diff = "0.1"
|
||||
log = "0.4.18"
|
||||
derive_more = "0.99.17"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "1.3.0"
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,11 @@ use std::{
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{indent, write_items_indented};
|
||||
use crate::{
|
||||
indent,
|
||||
parsed::asm::{AbsoluteSymbolPath, Part},
|
||||
write_indented_by, write_items_indented,
|
||||
};
|
||||
|
||||
use super::{
|
||||
AnalysisASMFile, AssignmentStatement, CallableSymbol, CallableSymbolDefinitionRef,
|
||||
@@ -17,9 +21,36 @@ use super::{
|
||||
|
||||
impl<T: Display> Display for AnalysisASMFile<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
let mut current_path = AbsoluteSymbolPath::default();
|
||||
|
||||
for (name, machine) in &self.machines {
|
||||
write!(f, "machine {name}{machine}")?;
|
||||
let [diff @ .., Part::Named(machine_name)] = &name.relative_to(¤t_path).parts[..]
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
for part in diff {
|
||||
match part {
|
||||
Part::Super => {
|
||||
current_path.pop();
|
||||
write_indented_by(f, "}\n", current_path.parts.len())?;
|
||||
}
|
||||
Part::Named(m) => {
|
||||
write_indented_by(f, format!("mod {m} {{\n"), current_path.parts.len())?;
|
||||
current_path.push(m.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_indented_by(
|
||||
f,
|
||||
format!("machine {machine_name}{machine}"),
|
||||
current_path.parts.len(),
|
||||
)?;
|
||||
}
|
||||
for (i, _) in current_path.parts.iter().enumerate().rev() {
|
||||
write_indented_by(f, "}\n", i)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -247,3 +278,59 @@ impl Display for IncompatibleSet {
|
||||
write!(f, "{}", self.0.iter().format(", "))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::parsed::asm::parse_absolute_path;
|
||||
use number::GoldilocksField;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn display_asm_analysis_file() {
|
||||
let file = AnalysisASMFile::<GoldilocksField> {
|
||||
machines: [
|
||||
"::x::Y",
|
||||
"::x::r::T",
|
||||
"::x::f::Y",
|
||||
"::M",
|
||||
"::t::x::y::R",
|
||||
"::t::F",
|
||||
"::X",
|
||||
]
|
||||
.into_iter()
|
||||
.map(|s| (parse_absolute_path(s), Machine::default()))
|
||||
.collect(),
|
||||
};
|
||||
assert_eq!(
|
||||
file.to_string(),
|
||||
r#"machine M {
|
||||
}
|
||||
machine X {
|
||||
}
|
||||
mod t {
|
||||
machine F {
|
||||
}
|
||||
mod x {
|
||||
mod y {
|
||||
machine R {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mod x {
|
||||
machine Y {
|
||||
}
|
||||
mod f {
|
||||
machine Y {
|
||||
}
|
||||
}
|
||||
mod r {
|
||||
machine T {
|
||||
}
|
||||
}
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ pub fn evaluate_unary_operation<T: FieldElement>(op: UnaryOperator, v: T) -> T {
|
||||
}
|
||||
|
||||
/// quick and dirty String to String indentation
|
||||
fn indent<S: ToString>(s: S, indentation: usize) -> String {
|
||||
pub fn indent<S: ToString>(s: S, indentation: usize) -> String {
|
||||
s.to_string()
|
||||
.split('\n')
|
||||
.map(|line| match line {
|
||||
@@ -87,6 +87,14 @@ fn indent<S: ToString>(s: S, indentation: usize) -> String {
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
pub fn write_indented_by<S, W>(f: &mut W, s: S, indentation: usize) -> Result
|
||||
where
|
||||
S: Display,
|
||||
W: Write,
|
||||
{
|
||||
write!(f, "{}", indent(s, indentation))
|
||||
}
|
||||
|
||||
fn write_items<S, I, W>(f: &mut W, items: I) -> Result
|
||||
where
|
||||
S: Display,
|
||||
@@ -112,7 +120,8 @@ where
|
||||
W: Write,
|
||||
{
|
||||
for item in items.into_iter() {
|
||||
writeln!(f, "{}", indent(item, by))?;
|
||||
write_indented_by(f, item, by)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::{fmt::Display, iter::once};
|
||||
use std::{
|
||||
fmt::Display,
|
||||
iter::{once, repeat},
|
||||
};
|
||||
|
||||
use number::AbstractNumberType;
|
||||
|
||||
@@ -121,6 +124,7 @@ pub struct AbsoluteSymbolPath {
|
||||
/// Panics if the path does not start with '::'.
|
||||
pub fn parse_absolute_path(s: &str) -> AbsoluteSymbolPath {
|
||||
match s.strip_prefix("::") {
|
||||
Some("") => AbsoluteSymbolPath::default(),
|
||||
Some(s) => s
|
||||
.split("::")
|
||||
.fold(AbsoluteSymbolPath::default(), |path, part| {
|
||||
@@ -131,12 +135,48 @@ pub fn parse_absolute_path(s: &str) -> AbsoluteSymbolPath {
|
||||
}
|
||||
|
||||
impl AbsoluteSymbolPath {
|
||||
/// Removes and returns the last path component (unless empty).
|
||||
pub fn pop(&mut self) -> Option<String> {
|
||||
self.parts.pop()
|
||||
}
|
||||
}
|
||||
|
||||
impl AbsoluteSymbolPath {
|
||||
/// Appends a part to the end of the path.
|
||||
pub fn push(&mut self, part: String) {
|
||||
self.parts.push(part);
|
||||
}
|
||||
|
||||
/// Returns the relative path from base to self.
|
||||
/// In other words, base.join(self.relative_to(base)) == self.
|
||||
pub fn relative_to(&self, base: &AbsoluteSymbolPath) -> SymbolPath {
|
||||
let common_prefix_len = self.common_prefix(base).parts.len();
|
||||
// Start with max(0, base.parts.len() - common_root.parts.len())
|
||||
// repetitions of "super".
|
||||
let parts = repeat(Part::Super)
|
||||
.take(base.parts.len().saturating_sub(common_prefix_len))
|
||||
// append the parts of self after the common root.
|
||||
.chain(
|
||||
self.parts
|
||||
.iter()
|
||||
.skip(common_prefix_len)
|
||||
.cloned()
|
||||
.map(Part::Named),
|
||||
)
|
||||
.collect();
|
||||
SymbolPath { parts }
|
||||
}
|
||||
|
||||
/// Returns the common prefix of two paths.
|
||||
pub fn common_prefix(&self, other: &AbsoluteSymbolPath) -> AbsoluteSymbolPath {
|
||||
let parts = self
|
||||
.parts
|
||||
.iter()
|
||||
.zip(other.parts.iter())
|
||||
.map_while(|(a, b)| if a == b { Some(a.clone()) } else { None })
|
||||
.collect();
|
||||
|
||||
AbsoluteSymbolPath { parts }
|
||||
}
|
||||
|
||||
/// Resolves a relative path in the context of this absolute path.
|
||||
pub fn join<P: Into<SymbolPath> + Display>(mut self, other: P) -> Self {
|
||||
for part in other.into().parts {
|
||||
@@ -339,3 +379,80 @@ pub struct Param<T> {
|
||||
pub index: Option<T>,
|
||||
pub ty: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn common_prefix() {
|
||||
assert_eq!(
|
||||
parse_absolute_path("::a::b").common_prefix(&parse_absolute_path("::a::c")),
|
||||
parse_absolute_path("::a")
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::a::b").common_prefix(&parse_absolute_path("::a")),
|
||||
parse_absolute_path("::a")
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::a").common_prefix(&parse_absolute_path("::a::c")),
|
||||
parse_absolute_path("::a")
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::x").common_prefix(&parse_absolute_path("::y::t")),
|
||||
parse_absolute_path("::")
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::x::r::v").common_prefix(&parse_absolute_path("::x::r::t")),
|
||||
parse_absolute_path("::x::r")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relative_to() {
|
||||
assert_eq!(
|
||||
parse_absolute_path("::a::b")
|
||||
.relative_to(&parse_absolute_path("::a::c"))
|
||||
.to_string(),
|
||||
"super::b".to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::a::b")
|
||||
.relative_to(&parse_absolute_path("::a"))
|
||||
.to_string(),
|
||||
"b".to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::x")
|
||||
.relative_to(&parse_absolute_path("::y::t"))
|
||||
.to_string(),
|
||||
"super::super::x".to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::x::r::v")
|
||||
.relative_to(&parse_absolute_path("::x::r"))
|
||||
.to_string(),
|
||||
"v".to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::x")
|
||||
.relative_to(&parse_absolute_path("::x::t::k"))
|
||||
.to_string(),
|
||||
"super::super".to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
parse_absolute_path("::x")
|
||||
.relative_to(&parse_absolute_path("::x"))
|
||||
.to_string(),
|
||||
"".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relative_to_join() {
|
||||
let v = parse_absolute_path("::x::r::v");
|
||||
let base = parse_absolute_path("::x::t");
|
||||
let rel = v.relative_to(&base);
|
||||
assert_eq!(base.join(rel), v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ use ast::parsed::{
|
||||
folder::Folder,
|
||||
};
|
||||
|
||||
/// Changes all symbol references (symbol paths) from relative paths
|
||||
/// to absolute paths, and removes all import statements.
|
||||
pub fn canonicalize_paths<T: FieldElement>(
|
||||
program: ASMProgram<T>,
|
||||
) -> Result<ASMProgram<T>, String> {
|
||||
|
||||
Reference in New Issue
Block a user