Skip to content

Commit

Permalink
refactoring builtins
Browse files Browse the repository at this point in the history
  • Loading branch information
katat committed Apr 7, 2024
1 parent c2d9aac commit aef55a1
Show file tree
Hide file tree
Showing 19 changed files with 1,219 additions and 631 deletions.
279 changes: 142 additions & 137 deletions src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,158 +27,163 @@ use std::hash::Hash;

use itertools::Itertools;

use crate::backends::kimchi::Kimchi;
use crate::backends::Backend;
use crate::circuit_writer::writer::AnnotatedCell;
use crate::circuit_writer::{CircuitWriter, DebugInfo};
use crate::compiler::Sources;
use crate::constants::KimchiField;
use crate::helpers::PrettyField;
use crate::{
circuit_writer::{Gate, Wiring},
constants::{Field, Span},
};


impl<B: Backend> CircuitWriter<B> {
pub fn generate_asm(&self, sources: &Sources, debug: bool) -> String {
let mut res = "".to_string();

// version
res.push_str("@ noname.0.7.0\n\n");

// vars
let mut vars = OrderedHashSet::default();

let gates = self.compiled_gates();

for Gate { coeffs, .. } in gates {
extract_vars_from_coeffs(&mut vars, coeffs);
}

if debug && !vars.is_empty() {
title(&mut res, "VARS");
}

for (idx, var) in vars.iter().enumerate() {
writeln!(res, "c{idx} = {}", var.pretty()).unwrap();
}

// gates
if debug {
title(&mut res, "GATES");
}

for (row, (Gate { typ, coeffs }, debug_info)) in
gates.iter().zip(&self.debug_info).enumerate()
{
// gate #
if debug {
writeln!(res, "╭{s}", s = "─".repeat(80)).unwrap();
write!(res, "│ GATE {row} - ").unwrap();
}

// gate
write!(res, "{typ:?}").unwrap();

// coeffs
{
let coeffs = parse_coeffs(&vars, coeffs);
if !coeffs.is_empty() {
res.push('<');
res.push_str(&coeffs.join(","));
res.push_str(">");
}
}

res.push('\n');

if debug {
// source
self.display_source(&mut res, sources, &[debug_info.clone()]);

// note
res.push_str(" ▲\n");
writeln!(res, " ╰── {note}", note = debug_info.note).unwrap();

//
res.push_str("\n\n");
}
}

// wiring
if debug {
title(&mut res, "WIRING");
}

let mut cycles: Vec<_> = self
.wiring
.values()
.map(|w| match w {
Wiring::NotWired(_) => None,
Wiring::Wired(annotated_cells) => Some(annotated_cells),
})
.filter(Option::is_some)
.flatten()
.collect();

// we must have a deterministic sort for the cycles,
// otherwise the same circuit might have different representations
cycles.sort();

for annotated_cells in cycles {
let (cells, debug_infos): (Vec<_>, Vec<_>) = annotated_cells
.into_iter()
.map(|AnnotatedCell { cell, debug }| (cell.clone(), debug.clone()))
.unzip();

if debug {
self.display_source(&mut res, sources, &debug_infos);
}

let s = cells.iter().map(|cell| format!("{cell}")).join(" -> ");
writeln!(res, "{s}").unwrap();

if debug {
writeln!(res, "\n").unwrap();
}
}

res
self.backend.generate_asm(sources, debug)
// let mut res = "".to_string();

// // version
// res.push_str("@ noname.0.7.0\n\n");

// // vars
// let mut vars = OrderedHashSet::default();

// let gates = self.compiled_gates();

// for Gate { coeffs, .. } in gates {
// extract_vars_from_coeffs(&mut vars, coeffs);
// }

// if debug && !vars.is_empty() {
// title(&mut res, "VARS");
// }

// for (idx, var) in vars.iter().enumerate() {
// writeln!(res, "c{idx} = {}", var.pretty()).unwrap();
// }

// // gates
// if debug {
// title(&mut res, "GATES");
// }

// for (row, (Gate { typ, coeffs }, debug_info)) in
// gates.iter().zip(&self.debug_info).enumerate()
// {
// // gate #
// if debug {
// writeln!(res, "╭{s}", s = "─".repeat(80)).unwrap();
// write!(res, "│ GATE {row} - ").unwrap();
// }

// // gate
// write!(res, "{typ:?}").unwrap();

// // coeffs
// {
// let coeffs = parse_coeffs(&vars, coeffs);
// if !coeffs.is_empty() {
// res.push('<');
// res.push_str(&coeffs.join(","));
// res.push_str(">");
// }
// }

// res.push('\n');

// if debug {
// // source
// self.display_source(&mut res, sources, &[debug_info.clone()]);

// // note
// res.push_str(" ▲\n");
// writeln!(res, " ╰── {note}", note = debug_info.note).unwrap();

// //
// res.push_str("\n\n");
// }
// }

// // wiring
// if debug {
// title(&mut res, "WIRING");
// }

// let mut cycles: Vec<_> = self
// .wiring
// .values()
// .map(|w| match w {
// Wiring::NotWired(_) => None,
// Wiring::Wired(annotated_cells) => Some(annotated_cells),
// })
// .filter(Option::is_some)
// .flatten()
// .collect();

// // we must have a deterministic sort for the cycles,
// // otherwise the same circuit might have different representations
// cycles.sort();

// for annotated_cells in cycles {
// let (cells, debug_infos): (Vec<_>, Vec<_>) = annotated_cells
// .into_iter()
// .map(|AnnotatedCell { cell, debug }| (cell.clone(), debug.clone()))
// .unzip();

// if debug {
// self.display_source(&mut res, sources, &debug_infos);
// }

// let s = cells.iter().map(|cell| format!("{cell}")).join(" -> ");
// writeln!(res, "{s}").unwrap();

// if debug {
// writeln!(res, "\n").unwrap();
// }
// }

// res
}

fn display_source(&self, res: &mut String, sources: &Sources, debug_infos: &[DebugInfo]) {
for DebugInfo { span, note } in debug_infos {
// find filename and source
let (file, source) = sources.get(&span.filename_id).expect("source not found");

// top corner
res.push('╭');
res.push_str(&"─".repeat(80));
res.push('\n');

// display filename
writeln!(res, "│ FILE: {}", file).unwrap();
writeln!(res, "│{s}", s = "─".repeat(80)).unwrap();

// source
res.push_str("│ ");
let (line_number, start, line) = find_exact_line(source, *span);
let header = format!("{line_number}: ");
writeln!(res, "{header}{line}").unwrap();

// caption
res.push('│');
res.push_str(&" ".repeat(header.len() + 1 + span.start - start));
res.push_str(&"^".repeat(span.len));
res.push('\n');
}

// bottom corner
res.push('╰');
res.push_str(&"─".repeat(80));
res.push('\n');
self.backend.display_source(res, sources, debug_infos);
// for DebugInfo { span, note } in debug_infos {
// // find filename and source
// let (file, source) = sources.get(&span.filename_id).expect("source not found");

// // top corner
// res.push('╭');
// res.push_str(&"─".repeat(80));
// res.push('\n');

// // display filename
// writeln!(res, "│ FILE: {}", file).unwrap();
// writeln!(res, "│{s}", s = "─".repeat(80)).unwrap();

// // source
// res.push_str("│ ");
// let (line_number, start, line) = find_exact_line(source, *span);
// let header = format!("{line_number}: ");
// writeln!(res, "{header}{line}").unwrap();

// // caption
// res.push('│');
// res.push_str(&" ".repeat(header.len() + 1 + span.start - start));
// res.push_str(&"^".repeat(span.len));
// res.push('\n');
// }

// // bottom corner
// res.push('╰');
// res.push_str(&"─".repeat(80));
// res.push('\n');
}
}

fn extract_vars_from_coeffs<F: Field + PrettyField>(vars: &mut OrderedHashSet<F>, coeffs: &[F]) {
pub fn extract_vars_from_coeffs<F: Field + PrettyField>(vars: &mut OrderedHashSet<F>, coeffs: &[F]) {
for coeff in coeffs {
let s = coeff.pretty();
if s.len() >= 5 {
Expand All @@ -187,7 +192,7 @@ fn extract_vars_from_coeffs<F: Field + PrettyField>(vars: &mut OrderedHashSet<F>
}
}

fn parse_coeffs<F: Field + PrettyField>(vars: &OrderedHashSet<F>, coeffs: &[F]) -> Vec<String> {
pub fn parse_coeffs<F: Field + PrettyField>(vars: &OrderedHashSet<F>, coeffs: &[F]) -> Vec<String> {
let mut coeffs: Vec<_> = coeffs
.iter()
.map(|x| {
Expand All @@ -209,7 +214,7 @@ fn parse_coeffs<F: Field + PrettyField>(vars: &OrderedHashSet<F>, coeffs: &[F])
coeffs
}

fn find_exact_line(source: &str, span: Span) -> (usize, usize, &str) {
pub fn find_exact_line(source: &str, span: Span) -> (usize, usize, &str) {
let ss = source.as_bytes();
let mut start = span.start;
let mut end = span.end();
Expand All @@ -227,7 +232,7 @@ fn find_exact_line(source: &str, span: Span) -> (usize, usize, &str) {
(line_number, start, line)
}

fn title(res: &mut String, s: &str) {
pub fn title(res: &mut String, s: &str) {
writeln!(res, "╭{s}╮", s = "─".repeat(s.len())).unwrap();
writeln!(res, "│{s}│", s = s).unwrap();
writeln!(res, "╰{s}╯", s = "─".repeat(s.len())).unwrap();
Expand Down
Loading

0 comments on commit aef55a1

Please sign in to comment.