Skip to content

Commit

Permalink
feat: multi dimensional access (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
brech1 authored Jan 30, 2024
1 parent e63ef59 commit 9090c88
Show file tree
Hide file tree
Showing 6 changed files with 582 additions and 513 deletions.
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ resolver = "1" # Fixes lalrpop issue, see: https://github.com/lalrpop/lalrpop/is
[dependencies]
clap = "2.34.0"
dotenv = "0.15.0"
env_logger = "0.10.1"
env_logger = "0.11.1"
log = "0.4.20"
regex = "1.10.2"
rand = "0.8.5"
regex = "1.10.3"
serde_json = "1.0"
serde = { version = "1.0.193", features = ["derive"] }
thiserror = "1.0.50"
serde = { version = "1.0.196", features = ["derive"] }
thiserror = "1.0.56"

# DSL
circom-circom_algebra = { git = "https://github.com/iden3/circom", package = "circom_algebra"}
Expand Down
5 changes: 3 additions & 2 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use circom_compiler::compiler_interface;
use circom_compiler::compiler_interface::{Config, VCP};
use circom_constraint_generation::{build_circuit, BuildConfig};
use circom_program_structure::error_definition::Report;
use circom_program_structure::program_archive::ProgramArchive;
use circom_type_analysis::check_types::check_types;
Expand Down Expand Up @@ -61,6 +62,7 @@ pub struct ExecutionConfig {
pub r1cs: String,
pub sym: String,
pub json_constraints: String,
pub json_substitutions: String,
pub no_rounds: usize,
pub flag_s: bool,
pub flag_f: bool,
Expand All @@ -79,11 +81,10 @@ pub fn execute_project(
program_archive: ProgramArchive,
config: ExecutionConfig,
) -> Result<VCP, ()> {
use circom_constraint_generation::{build_circuit, BuildConfig};

let build_config = BuildConfig {
no_rounds: config.no_rounds,
flag_json_sub: config.json_substitution_flag,
json_substitutions: config.json_substitutions,
flag_s: config.flag_s,
flag_f: config.flag_f,
flag_p: config.flag_p,
Expand Down
110 changes: 51 additions & 59 deletions src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use std::collections::HashMap;

use crate::circuit::{AGateType, ArithmeticCircuit};
use crate::program::ProgramError;
use crate::runtime::{DataContent, Runtime, ContextOrigin};
use crate::traverse::traverse_sequence_of_statements;
use crate::runtime::{ContextOrigin, DataAccess, DataType, Runtime};
use crate::traverse::{build_access, traverse_sequence_of_statements};
use circom_circom_algebra::num_traits::ToPrimitive;
use circom_program_structure::ast::{Access, Expression, ExpressionInfixOpcode, Statement};
use circom_program_structure::ast::{Expression, ExpressionInfixOpcode, Statement};
use circom_program_structure::program_archive::ProgramArchive;
use log::debug;

Expand All @@ -34,7 +34,7 @@ pub fn execute_statement(
loop {
let res = execute_expression(ac, runtime, cond, program_archive)?;
execute_statement(ac, runtime, stmt, program_archive)?;
if res == 0 {
if res == Some(0) {
break;
}
}
Expand All @@ -48,7 +48,7 @@ pub fn execute_statement(
} => {
let res = execute_expression(ac, runtime, cond, program_archive)?;
let else_case = else_case.as_ref().map(|e| e.as_ref());
if res == 0 {
if res == Some(0) {
if let Option::Some(else_stmt) = else_case {
execute_statement(ac, runtime, else_stmt, program_archive)
} else {
Expand All @@ -61,40 +61,39 @@ pub fn execute_statement(
Statement::Substitution {
var, access, rhe, ..
} => {
let mut name_access = String::from(var);
for a in access.iter() {
match a {
Access::ArrayAccess(expr) => {
debug!("Array access found");
let dim_u32_str = execute_expression(ac, runtime, expr, program_archive)?;
name_access.push('_');
name_access.push_str(&dim_u32_str.to_string());
debug!("Change var name to {}", name_access);
}
Access::ComponentAccess(_) => {
todo!("Component access not handled");
}
}
}
// This corresponds to a variable assignment.
let access = build_access(runtime, ac, program_archive, var, access)?;

// Get the value of the right hand expression
let rhe_val = execute_expression(ac, runtime, rhe, program_archive)?;

// Declare the variable if it is not declared yet
let ctx = runtime.get_current_context()?;
if ctx.get_data_item(&name_access).is_err() {
ctx.declare_variable(&name_access)?;
let declare = ctx.declare_item(DataType::Variable, &access.get_name(), &[]);
if declare.is_ok() {
declare?;
}
ctx.set_data_item(&name_access, DataContent::Scalar(rhe_val))?;

// Set the variable value
ctx.set_variable(access, rhe_val)?;

Ok(())
}
Statement::Return { value, .. } => {
debug!("Return expression found");
let access = DataAccess::new("return".to_string(), vec![]);
let res = execute_expression(ac, runtime, value, program_archive)?;
debug!("RETURN {}", res);
debug!("RETURN {:?}", res);

let ctx = runtime.get_current_context()?;
ctx.declare_variable("RETURN");
ctx.set_data_item("RETURN", DataContent::Scalar(res));
let declare = ctx.declare_item(DataType::Variable, &access.get_name(), &[]);

// Added check to avoid panic when the return is already declared
if declare.is_ok() {
declare?;
}

ctx.set_variable(access, res)?;

Ok(())
}
Statement::Block { stmts, .. } => {
Expand All @@ -115,36 +114,23 @@ pub fn execute_expression(
runtime: &mut Runtime,
expression: &Expression,
program_archive: &ProgramArchive,
) -> Result<u32, ProgramError> {
) -> Result<Option<u32>, ProgramError> {
match expression {
Expression::Number(_, value) => Ok(value.to_u32().ok_or(ProgramError::ParsingError)?),
Expression::Number(_, value) => Ok(value.to_u32()),
Expression::InfixOp {
lhe, infix_op, rhe, ..
} => {
let lhs_op = execute_expression(ac, runtime, lhe, program_archive)?;
let rhs_op = execute_expression(ac, runtime, rhe, program_archive)?;
let lhs_op = execute_expression(ac, runtime, lhe, program_archive)?
.ok_or(ProgramError::EmptyDataItem)?;
let rhs_op = execute_expression(ac, runtime, rhe, program_archive)?
.ok_or(ProgramError::EmptyDataItem)?;

Ok(execute_infix_op(&lhs_op, &rhs_op, infix_op))
Ok(Some(execute_infix_op(&lhs_op, &rhs_op, infix_op)))
}
Expression::Variable { name, access, .. } => {
let mut name_access = String::from(name);
for a in access.iter() {
match a {
Access::ArrayAccess(expr) => {
debug!("Array access found");
let dim_u32 = execute_expression(ac, runtime, expr, program_archive)?;
name_access.push('_');
name_access.push_str(&dim_u32.to_string());
debug!("Changed var name to {}", name_access);
}
Access::ComponentAccess(_) => {
todo!("Component access found");
}
}
}

let access = build_access(runtime, ac, program_archive, name, access)?;
let ctx = runtime.get_current_context()?;
Ok(ctx.get_data_item(&name_access)?.get_u32()?)
Ok(ctx.get_variable(&access)?)
}
Expression::Call { id, args, .. } => {
debug!("Call found {}", id);
Expand All @@ -157,15 +143,16 @@ pub fn execute_expression(
program_archive.get_template_data(id).get_name_of_params()
};

let mut args_map = HashMap::new();
let mut args_map: HashMap<String, u32> = HashMap::new();

// We start by setting argument values to argument names
for (_arg_name, arg_value) in arg_names.iter().zip(args) {
for (arg_name, arg_value) in arg_names.iter().zip(args) {
// We set arg_name to have arg_value
// Because arg_value is an expression (constant, variable, or an infix operation or a function call) we need to execute to have the actual value
let value = execute_expression(ac, runtime, arg_value, program_archive)?;
let value = execute_expression(ac, runtime, arg_value, program_archive)?
.ok_or(ProgramError::EmptyDataItem)?;
// We cache this to args hashmap
args_map.insert(_arg_name, value);
args_map.insert(arg_name.to_string(), value);
}

// Here we need to spawn a new context for calling a function or wiring with a component (template)
Expand All @@ -174,26 +161,31 @@ pub fn execute_expression(
let ctx = runtime.get_current_context()?;

// Now we put args to use
for (_arg_name, arg_value) in args_map.iter() {
let _ = ctx.declare_variable(&_arg_name);
let _ = ctx.set_data_item(_arg_name, DataContent::Scalar(*(arg_value)));
for (arg_name, &arg_value) in args_map.iter() {
// TODO: Review, all items are unidimensional
ctx.declare_item(DataType::Variable, arg_name, &[])?;
ctx.set_variable(
DataAccess::new(arg_name.to_string(), vec![]),
Some(arg_value),
)?;
}

let _body = if functions.contains(id) {
program_archive.get_function_data(id).get_body_as_vec()
} else {
program_archive.get_template_data(id).get_body_as_vec()
};

traverse_sequence_of_statements(ac, runtime, _body, program_archive, true)?;

if functions.contains(id) {
// let ret = ctx.get_data_item("RETURN").unwrap().get_u32().unwrap();
// runtime.pop_context();
Ok(0)
debug!("temp return");
Ok(Some(0))
} else {
// runtime.pop_context();
Ok(0)
Ok(Some(0))
}

// Err(ProgramError::CallError)
Expand Down
4 changes: 4 additions & 0 deletions src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ pub enum ProgramError {
AnalysisError,
#[error("Call error")]
CallError,
#[error("Empty data item")]
EmptyDataItem,
#[error("Invalid data type")]
InvalidDataType,
#[error("Parsing error")]
ParsingError,
#[error("Context error: {0}")]
Expand Down
Loading

0 comments on commit 9090c88

Please sign in to comment.