From 19dedf6ba1c209130d2fbcd8ec6d942003ef5195 Mon Sep 17 00:00:00 2001 From: Kata Choi Date: Fri, 27 Sep 2024 16:11:38 +0800 Subject: [PATCH] feat: log builtin (#193) --- src/backends/r1cs/mod.rs | 28 +++++++++++++++++++++++++++- src/stdlib/builtins.rs | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/backends/r1cs/mod.rs b/src/backends/r1cs/mod.rs index 4581a4f81..17f7fdac2 100644 --- a/src/backends/r1cs/mod.rs +++ b/src/backends/r1cs/mod.rs @@ -39,12 +39,38 @@ impl CellVar { impl BackendVar for LinearCombination {} +impl std::fmt::Debug for LinearCombination { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // format the linear combination as a single string + let mut lc = String::new(); + for (i, (var, factor)) in self.terms.iter().enumerate() { + if i > 0 { + lc.push_str(" + "); + } + + // format the factor + let factor = factor.pretty(); + match factor.as_str() { + "1" => lc.push_str(&format!("v_{}", var.index)), + _ => lc.push_str(&format!("{} * v_{}", factor, var.index)), + } + } + // constant + if self.constant != F::zero() { + lc.push_str(&format!(" + {}", self.constant.pretty())); + } + + // Write the formatted string to the formatter + write!(f, "{}", lc) + } +} + /// Linear combination of variables and constants. /// For example, the linear combination is represented as a * f_a + b * f_b + f_c /// f_a and f_b are the coefficients of a and b respectively. /// a and b are represented by CellVar. /// The constant f_c is represented by the constant field, will always multiply with the variable at index 0 which is always 1. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] pub struct LinearCombination where F: BackendField, diff --git a/src/stdlib/builtins.rs b/src/stdlib/builtins.rs index 3a672e54f..2ece6c5de 100644 --- a/src/stdlib/builtins.rs +++ b/src/stdlib/builtins.rs @@ -7,6 +7,7 @@ use crate::{ circuit_writer::{CircuitWriter, VarInfo}, constants::Span, error::{Error, ErrorKind, Result}, + helpers::PrettyField, parser::types::{GenericParameters, TyKind}, var::{ConstOrCell, Var}, }; @@ -14,10 +15,13 @@ use crate::{ use super::{FnInfoType, Module}; pub const QUALIFIED_BUILTINS: &str = "std/builtins"; -pub const BUILTIN_FN_NAMES: [&str; 2] = ["assert", "assert_eq"]; +pub const BUILTIN_FN_NAMES: [&str; 3] = ["assert", "assert_eq", "log"]; const ASSERT_FN: &str = "assert(condition: Bool)"; const ASSERT_EQ_FN: &str = "assert_eq(lhs: Field, rhs: Field)"; +// todo: currently only supports a single field var +// to support all the types, we can bypass the type check for this log function for now +const LOG_FN: &str = "log(var: Field)"; pub struct BuiltinsLib {} @@ -25,7 +29,11 @@ impl Module for BuiltinsLib { const MODULE: &'static str = "builtins"; fn get_fns() -> Vec<(&'static str, FnInfoType)> { - vec![(ASSERT_FN, assert_fn), (ASSERT_EQ_FN, assert_eq_fn)] + vec![ + (ASSERT_FN, assert_fn), + (ASSERT_EQ_FN, assert_eq_fn), + (LOG_FN, log_fn), + ] } } @@ -121,3 +129,30 @@ fn assert_fn( Ok(None) } + +/// Logging +fn log_fn( + compiler: &mut CircuitWriter, + generics: &GenericParameters, + vars: &[VarInfo], + span: Span, +) -> Result>> { + println!("---log span: {:?}---", span); + for var in vars { + // typ + println!("typ: {:?}", var.typ); + // mutable + println!("mutable: {:?}", var.mutable); + // var + var.var.iter().for_each(|v| match v { + ConstOrCell::Const(cst) => { + println!("cst: {:?}", cst.pretty()); + } + ConstOrCell::Cell(cvar) => { + println!("cvar: {:?}", cvar); + } + }); + } + + Ok(None) +}