Skip to content

Commit

Permalink
wip: refactor using ark_ff::Field
Browse files Browse the repository at this point in the history
  • Loading branch information
katat committed Mar 28, 2024
1 parent 9b0b773 commit aa9687a
Show file tree
Hide file tree
Showing 24 changed files with 233 additions and 225 deletions.
6 changes: 3 additions & 3 deletions src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use crate::{
helpers::PrettyField as _,
};

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

Expand Down Expand Up @@ -177,7 +177,7 @@ impl CircuitWriter {
}
}

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

fn parse_coeffs(vars: &OrderedHashSet<Field>, coeffs: &[Field]) -> Vec<String> {
fn parse_coeffs<F: Field>(vars: &OrderedHashSet<F>, coeffs: &[F]) -> Vec<String> {
let mut coeffs: Vec<_> = coeffs
.iter()
.map(|x| {
Expand Down
27 changes: 14 additions & 13 deletions src/circuit_writer/fn_env.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::collections::HashMap;

use crate::{parser::types::TyKind, var::Var};
use crate::constants::Field;

/// Information about a variable.
#[derive(Debug, Clone)]
pub struct VarInfo {
pub struct VarInfo<F> where F: Field {
/// The variable.
pub var: Var,
pub var: Var<F>,

// TODO: we could also store this on the expression node... but I think this is lighter
pub mutable: bool,
Expand All @@ -17,20 +18,20 @@ pub struct VarInfo {
pub typ: Option<TyKind>,
}

impl VarInfo {
pub fn new(var: Var, mutable: bool, typ: Option<TyKind>) -> Self {
impl<F: Field> VarInfo<F> {
pub fn new(var: Var<F>, mutable: bool, typ: Option<TyKind>) -> Self {
Self { var, mutable, typ }
}

pub fn reassign(&self, var: Var) -> Self {
pub fn reassign(&self, var: Var<F>) -> Self {
Self {
var,
mutable: self.mutable,
typ: self.typ.clone(),
}
}

pub fn reassign_range(&self, var: Var, start: usize, len: usize) -> Self {
pub fn reassign_range(&self, var: Var<F>, start: usize, len: usize) -> Self {
// sanity check
assert_eq!(var.len(), len);

Expand All @@ -53,7 +54,7 @@ impl VarInfo {
/// This include inputs and output of the function, as well as local variables.
/// You can think of it as a function call stack.
#[derive(Default, Debug, Clone)]
pub struct FnEnv {
pub struct FnEnv<F> where F: Field {
/// The current nesting level.
/// Starting at 0 (top level), and increasing as we go into a block.
current_scope: usize,
Expand All @@ -62,10 +63,10 @@ pub struct FnEnv {
/// and any other external variables created in the circuit
/// This needs to be garbage collected when we exit a scope.
/// Note: The `usize` is the scope in which the variable was created.
vars: HashMap<String, (usize, VarInfo)>,
vars: HashMap<String, (usize, VarInfo<F>)>,
}

impl FnEnv {
impl<F: Field> FnEnv<F> {
/// Creates a new FnEnv
pub fn new() -> Self {
Self::default()
Expand Down Expand Up @@ -101,7 +102,7 @@ impl FnEnv {

/// Stores type information about a local variable.
/// Note that we forbid shadowing at all scopes.
pub fn add_local_var(&mut self, var_name: String, var_info: VarInfo) {
pub fn add_local_var(&mut self, var_name: String, var_info: VarInfo<F>) {
let scope = self.current_scope;

if self
Expand All @@ -116,7 +117,7 @@ impl FnEnv {
/// Retrieves type information on a variable, given a name.
/// If the variable is not in scope, return false.
// TODO: return an error no?
pub fn get_local_var(&self, var_name: &str) -> VarInfo {
pub fn get_local_var(&self, var_name: &str) -> VarInfo<F> {
let (scope, var_info) = self
.vars
.get(var_name)
Expand All @@ -128,7 +129,7 @@ impl FnEnv {
var_info.clone()
}

pub fn reassign_local_var(&mut self, var_name: &str, var: Var) {
pub fn reassign_local_var(&mut self, var_name: &str, var: Var<F>) {
// get the scope first, we don't want to modify that
let (scope, var_info) = self
.vars
Expand All @@ -148,7 +149,7 @@ impl FnEnv {
}

/// Same as [Self::reassign_var], but only reassigns a specific range of the variable.
pub fn reassign_var_range(&mut self, var_name: &str, var: Var, start: usize, len: usize) {
pub fn reassign_var_range(&mut self, var_name: &str, var: Var<F>, start: usize, len: usize) {
// get the scope first, we don't want to modify that
let (scope, var_info) = self
.vars
Expand Down
34 changes: 17 additions & 17 deletions src/circuit_writer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ pub mod writer;

//#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug)]
pub struct CircuitWriter {
pub struct CircuitWriter<F> where F: Field {
/// The type checker state for the main module.
// Important: this field must not be used directly.
// This is because, depending on the value of [current_module],
// the type checker state might be this one, or one of the ones in [dependencies].
typed: TypeChecker,
typed: TypeChecker<F>,

/// Once this is set, you can generate a witness (and can't modify the circuit?)
// Note: I don't think we need this, but it acts as a nice redundant failsafe.
Expand All @@ -40,15 +40,15 @@ pub struct CircuitWriter {

/// This is how you compute the value of each variable during witness generation.
/// It is created during circuit generation.
pub(crate) witness_vars: HashMap<usize, Value>,
pub(crate) witness_vars: HashMap<usize, Value<F>>,

/// The execution trace table with vars as placeholders.
/// It is created during circuit generation,
/// and used by the witness generator.
pub(crate) rows_of_vars: Vec<Vec<Option<CellVar>>>,

/// The gates created by the circuit generation.
gates: Vec<Gate>,
gates: Vec<Gate<F>>,

/// The wiring of the circuit.
/// It is created during circuit generation.
Expand All @@ -65,7 +65,7 @@ pub struct CircuitWriter {
/// it will set this `public_output` variable again to the correct vars.
/// 3. During witness generation, the public output computation
/// is delayed until the very end.
pub(crate) public_output: Option<Var>,
pub(crate) public_output: Option<Var<F>>,

/// Indexes used by the private inputs
/// (this is useful to check that they appear in the circuit)
Expand All @@ -77,11 +77,11 @@ pub struct CircuitWriter {

/// This is used to implement the double generic gate,
/// which encodes two generic gates.
pub(crate) pending_generic_gate: Option<PendingGate>,
pub(crate) pending_generic_gate: Option<PendingGate<F>>,

/// We cache the association between a constant and its _constrained_ variable,
/// this is to avoid creating a new constraint every time we need to hardcode the same constant.
pub(crate) cached_constants: HashMap<Field, CellVar>,
pub(crate) cached_constants: HashMap<F, CellVar>,

/// A vector of debug information that maps to each row of the created circuit.
pub(crate) debug_info: Vec<DebugInfo>,
Expand All @@ -97,7 +97,7 @@ pub struct DebugInfo {
pub note: String,
}

impl CircuitWriter {
impl<F: Field> CircuitWriter<F> {
pub fn expr_type(&self, expr: &Expr) -> Option<&TyKind> {
self.typed.expr_type(expr)
}
Expand All @@ -111,19 +111,19 @@ impl CircuitWriter {
self.typed.struct_info(qualified)
}

pub fn fn_info(&self, qualified: &FullyQualified) -> Option<&FnInfo> {
pub fn fn_info(&self, qualified: &FullyQualified) -> Option<&FnInfo<F>> {
self.typed.fn_info(qualified)
}

pub fn const_info(&self, qualified: &FullyQualified) -> Option<&ConstInfo> {
pub fn const_info(&self, qualified: &FullyQualified) -> Option<&ConstInfo<F>> {
self.typed.const_info(qualified)
}

pub fn size_of(&self, typ: &TyKind) -> usize {
self.typed.size_of(typ)
}

pub fn add_local_var(&self, fn_env: &mut FnEnv, var_name: String, var_info: VarInfo) {
pub fn add_local_var(&self, fn_env: &mut FnEnv<F>, var_name: String, var_info: VarInfo<F>) {
// check for consts first
let qualified = FullyQualified::local(var_name.clone());
if let Some(_cst_info) = self.typed.const_info(&qualified) {
Expand All @@ -136,7 +136,7 @@ impl CircuitWriter {
fn_env.add_local_var(var_name, var_info)
}

pub fn get_local_var(&self, fn_env: &FnEnv, var_name: &str) -> VarInfo {
pub fn get_local_var(&self, fn_env: &FnEnv<F>, var_name: &str) -> VarInfo<F> {
// check for consts first
let qualified = FullyQualified::local(var_name.to_string());
if let Some(cst_info) = self.typed.const_info(&qualified) {
Expand All @@ -151,7 +151,7 @@ impl CircuitWriter {
/// Retrieves the [FnInfo] for the `main()` function.
/// This function should only be called if we know there's a main function,
/// if there's no main function it'll panic.
pub fn main_info(&self) -> Result<&FnInfo> {
pub fn main_info(&self) -> Result<&FnInfo<F>> {
let qualified = FullyQualified::local("main".to_string());
self.typed
.fn_info(&qualified)
Expand All @@ -163,9 +163,9 @@ impl CircuitWriter {
}
}

impl CircuitWriter {
impl<F: Field> CircuitWriter<F> {
/// Creates a global environment from the one created by the type checker.
fn new(typed: TypeChecker, double_generic_gate_optimization: bool) -> Self {
fn new(typed: TypeChecker<F>, double_generic_gate_optimization: bool) -> Self {
Self {
typed,
finalized: false,
Expand All @@ -185,9 +185,9 @@ impl CircuitWriter {
}

pub fn generate_circuit(
typed: TypeChecker,
typed: TypeChecker<F>,
double_generic_gate_optimization: bool,
) -> Result<CompiledCircuit> {
) -> Result<CompiledCircuit<F>> {
// create circuit writer
let mut circuit_writer = CircuitWriter::new(typed, double_generic_gate_optimization);

Expand Down
Loading

0 comments on commit aa9687a

Please sign in to comment.