Skip to content

Commit 8188bf6

Browse files
authored
Merge pull request #238 from varunthakore/generic-log
Implement generic log
2 parents 1b515e8 + 429888b commit 8188bf6

File tree

4 files changed

+238
-6
lines changed

4 files changed

+238
-6
lines changed

src/backends/kimchi/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub const NUM_REGISTERS: usize = kimchi::circuits::wires::COLUMNS;
4444

4545
use super::{Backend, BackendField, BackendVar};
4646

47+
use crate::mast::Mast;
48+
4749
impl BackendField for VestaField {
4850
fn to_circ_field(&self) -> circ_fields::FieldV {
4951
let mut opt = CircOpt::default();
@@ -416,10 +418,11 @@ impl Backend for KimchiVesta {
416418
self.compute_val(env, val, var.index)
417419
}
418420

419-
fn generate_witness(
421+
fn generate_witness<B: Backend>(
420422
&self,
421423
witness_env: &mut WitnessEnv<VestaField>,
422424
sources: &Sources,
425+
_typed: &Mast<B>,
423426
) -> Result<GeneratedWitness> {
424427
if !self.finalized {
425428
unreachable!("the circuit must be finalized before generating a witness");

src/backends/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ use self::{
2222
r1cs::{R1csBls12381Field, R1csBn254Field, R1CS},
2323
};
2424

25+
use crate::mast::Mast;
26+
2527
pub mod kimchi;
2628
pub mod r1cs;
2729

@@ -411,10 +413,11 @@ pub trait Backend: Clone {
411413
) -> Result<()>;
412414

413415
/// Generate the witness for a backend.
414-
fn generate_witness(
416+
fn generate_witness<B: Backend>(
415417
&self,
416418
witness_env: &mut WitnessEnv<Self::Field>,
417419
sources: &Sources,
420+
typed: &Mast<B>,
418421
) -> Result<Self::GeneratedWitness>;
419422

420423
/// Generate the asm for a backend.

src/backends/r1cs/mod.rs

Lines changed: 228 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ use crate::circuit_writer::VarInfo;
1717
use crate::compiler::Sources;
1818
use crate::constants::Span;
1919
use crate::error::{Error, ErrorKind, Result};
20+
use crate::mast::Mast;
21+
use crate::parser::types::{ModulePath, TyKind};
22+
use crate::type_checker::FullyQualified;
2023
use crate::var::ConstOrCell;
2124
use crate::{circuit_writer::DebugInfo, var::Value};
2225

@@ -485,10 +488,11 @@ where
485488

486489
/// Generate the witnesses
487490
/// This process should check if the constraints are satisfied.
488-
fn generate_witness(
491+
fn generate_witness<B: Backend>(
489492
&self,
490493
witness_env: &mut crate::witness::WitnessEnv<F>,
491494
sources: &Sources,
495+
typed: &Mast<B>,
492496
) -> crate::error::Result<Self::GeneratedWitness> {
493497
assert!(self.finalized, "the circuit is not finalized yet!");
494498

@@ -520,15 +524,69 @@ where
520524
let (line, _, line_str) = crate::utils::find_exact_line(source, *span);
521525
let line_str = line_str.trim_start();
522526
let dbg_msg = format!("[{filename}:{line}] `{line_str}` -> ");
523-
for cvar in var_info.var.iter() {
524-
match cvar {
527+
528+
match &var_info.typ {
529+
// Field
530+
Some(TyKind::Field { .. }) => match &var_info.var[0] {
525531
ConstOrCell::Const(cst) => {
526532
println!("{dbg_msg}{}", cst.pretty());
527533
}
528534
ConstOrCell::Cell(cell) => {
529535
let val = cell.evaluate(&witness);
530536
println!("{dbg_msg}{}", val.pretty());
531537
}
538+
},
539+
540+
// Bool
541+
Some(TyKind::Bool) => match &var_info.var[0] {
542+
ConstOrCell::Const(cst) => {
543+
let val = *cst == F::one();
544+
println!("{dbg_msg}{}", val);
545+
}
546+
ConstOrCell::Cell(cell) => {
547+
let val = cell.evaluate(&witness) == F::one();
548+
println!("{dbg_msg}{}", val);
549+
}
550+
},
551+
552+
// Array
553+
Some(TyKind::Array(b, s)) => {
554+
let (output, remaining) =
555+
log_array_type(&var_info.var.cvars, b, *s, &witness, typed, span);
556+
assert!(remaining.is_empty());
557+
println!("{dbg_msg}{}", output);
558+
}
559+
560+
// Custom types
561+
Some(TyKind::Custom {
562+
module,
563+
name: struct_name,
564+
}) => {
565+
let mut string_vec = Vec::new();
566+
let (output, remaining) = log_custom_type(
567+
module,
568+
struct_name,
569+
typed,
570+
&var_info.var.cvars,
571+
&witness,
572+
span,
573+
&mut string_vec,
574+
);
575+
assert!(remaining.is_empty());
576+
println!("{dbg_msg}{}{}", struct_name, output);
577+
}
578+
579+
// GenericSizedArray
580+
Some(TyKind::GenericSizedArray(_, _)) => {
581+
unreachable!("GenericSizedArray should be monomorphized")
582+
}
583+
584+
None => {
585+
return Err(Error::new(
586+
"log",
587+
ErrorKind::UnexpectedError("No type info for logging"),
588+
*span,
589+
))
532590
}
533591
}
534592
}
@@ -704,6 +762,173 @@ where
704762
}
705763
}
706764

765+
fn log_custom_type<F: BackendField, B: Backend>(
766+
module: &ModulePath,
767+
struct_name: &String,
768+
typed: &Mast<B>,
769+
var_info_var: &[ConstOrCell<F, LinearCombination<F>>],
770+
witness: &[F],
771+
span: &Span,
772+
string_vec: &mut Vec<String>,
773+
) -> (String, Vec<ConstOrCell<F, LinearCombination<F>>>) {
774+
let qualified = FullyQualified::new(module, struct_name);
775+
let struct_info = typed
776+
.struct_info(&qualified)
777+
.ok_or(
778+
typed
779+
.0
780+
.error(ErrorKind::UnexpectedError("struct not found"), *span),
781+
)
782+
.unwrap();
783+
784+
let mut remaining = var_info_var.to_vec();
785+
786+
for (field_name, field_typ) in &struct_info.fields {
787+
let len = typed.size_of(field_typ);
788+
match field_typ {
789+
TyKind::Field { .. } => match &remaining[0] {
790+
ConstOrCell::Const(cst) => {
791+
string_vec.push(format!("{field_name}: {}", cst.pretty()));
792+
remaining = remaining[len..].to_vec();
793+
}
794+
ConstOrCell::Cell(cell) => {
795+
let val = cell.evaluate(witness);
796+
string_vec.push(format!("{field_name}: {}", val.pretty()));
797+
remaining = remaining[len..].to_vec();
798+
}
799+
},
800+
801+
TyKind::Bool => match &remaining[0] {
802+
ConstOrCell::Const(cst) => {
803+
let val = *cst == F::one();
804+
string_vec.push(format!("{field_name}: {}", val));
805+
remaining = remaining[len..].to_vec();
806+
}
807+
ConstOrCell::Cell(cell) => {
808+
let val = cell.evaluate(witness) == F::one();
809+
string_vec.push(format!("{field_name}: {}", val));
810+
remaining = remaining[len..].to_vec();
811+
}
812+
},
813+
814+
TyKind::Array(b, s) => {
815+
let (output, new_remaining) =
816+
log_array_type(&remaining, b, *s, witness, typed, span);
817+
string_vec.push(format!("{field_name}: {}", output));
818+
remaining = new_remaining;
819+
}
820+
821+
TyKind::Custom {
822+
module,
823+
name: struct_name,
824+
} => {
825+
let mut custom_string_vec = Vec::new();
826+
let (output, new_remaining) = log_custom_type(
827+
module,
828+
struct_name,
829+
typed,
830+
&remaining,
831+
witness,
832+
span,
833+
&mut custom_string_vec,
834+
);
835+
string_vec.push(format!("{}: {}{}", field_name, struct_name, output));
836+
remaining = new_remaining;
837+
}
838+
839+
TyKind::GenericSizedArray(_, _) => {
840+
unreachable!("GenericSizedArray should be monomorphized")
841+
}
842+
}
843+
}
844+
845+
(format!("{{ {} }}", string_vec.join(", ")), remaining)
846+
}
847+
848+
fn log_array_type<F: BackendField, B: Backend>(
849+
var_info_var: &[ConstOrCell<F, LinearCombination<F>>],
850+
base_type: &TyKind,
851+
size: u32,
852+
witness: &[F],
853+
typed: &Mast<B>,
854+
span: &Span,
855+
) -> (String, Vec<ConstOrCell<F, LinearCombination<F>>>) {
856+
match base_type {
857+
TyKind::Field { .. } => {
858+
let values: Vec<String> = var_info_var
859+
.iter()
860+
.take(size as usize)
861+
.map(|cvar| match cvar {
862+
ConstOrCell::Const(cst) => cst.pretty(),
863+
ConstOrCell::Cell(cell) => cell.evaluate(witness).pretty(),
864+
})
865+
.collect();
866+
867+
let remaining = var_info_var[size as usize..].to_vec();
868+
(format!("[{}]", values.join(", ")), remaining)
869+
}
870+
871+
TyKind::Bool => {
872+
let values: Vec<String> = var_info_var
873+
.iter()
874+
.take(size as usize)
875+
.map(|cvar| match cvar {
876+
ConstOrCell::Const(cst) => {
877+
let val = *cst == F::one();
878+
val.to_string()
879+
}
880+
ConstOrCell::Cell(cell) => {
881+
let val = cell.evaluate(witness) == F::one();
882+
val.to_string()
883+
}
884+
})
885+
.collect();
886+
887+
let remaining = var_info_var[size as usize..].to_vec();
888+
(format!("[{}]", values.join(", ")), remaining)
889+
}
890+
891+
TyKind::Array(inner_type, inner_size) => {
892+
let mut nested_result = Vec::new();
893+
let mut remaining = var_info_var.to_vec();
894+
for _ in 0..size {
895+
let (chunk_result, new_remaining) =
896+
log_array_type(&remaining, inner_type, *inner_size, witness, typed, span);
897+
nested_result.push(chunk_result);
898+
remaining = new_remaining;
899+
}
900+
(format!("[{}]", nested_result.join(", ")), remaining)
901+
}
902+
903+
TyKind::Custom {
904+
module,
905+
name: struct_name,
906+
} => {
907+
let mut nested_result = Vec::new();
908+
let mut remaining = var_info_var.to_vec();
909+
for _ in 0..size {
910+
let mut string_vec = Vec::new();
911+
let (output, new_remaining) = log_custom_type(
912+
module,
913+
struct_name,
914+
typed,
915+
&remaining,
916+
witness,
917+
span,
918+
&mut string_vec,
919+
);
920+
nested_result.push(format!("{}{}", struct_name, output));
921+
remaining = new_remaining;
922+
}
923+
(format!("[{}]", nested_result.join(", ")), remaining)
924+
}
925+
926+
TyKind::GenericSizedArray(_, _) => {
927+
unreachable!("GenericSizedArray should be monomorphized")
928+
}
929+
}
930+
}
931+
707932
#[cfg(test)]
708933
mod tests {
709934
use crate::{

src/circuit_writer/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ impl<B: Backend> CircuitWriter<B> {
232232
witness_env: &mut WitnessEnv<B::Field>,
233233
sources: &Sources,
234234
) -> Result<B::GeneratedWitness> {
235-
self.backend.generate_witness(witness_env, sources)
235+
self.backend
236+
.generate_witness(witness_env, sources, &self.typed)
236237
}
237238

238239
fn handle_arg(

0 commit comments

Comments
 (0)