Skip to content

Commit

Permalink
fix: traverse infix op
Browse files Browse the repository at this point in the history
  • Loading branch information
brech1 committed Jan 8, 2024
1 parent 6040870 commit 9346327
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 28 deletions.
2 changes: 0 additions & 2 deletions src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,12 @@ pub fn execute_statement(
if let Some(val) = data_item.get_content() {
ctx.set_data_item(&name_access, val.clone())?;
} else {
// TODO: Review this, we're assigning a variable another's variable's name
ctx.set_data_item(&name_access, DataContent::Scalar(rhs))?;
}
Ok(())
}
Err(_) => {
ctx.declare_variable(&name_access)?;
// TODO: Review this, we're assigning a variable another's variable's name
ctx.set_data_item(&name_access, DataContent::Scalar(rhs))?;
Ok(())
}
Expand Down
33 changes: 24 additions & 9 deletions src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ impl Context {
/// Retrieves a reference to a data item by name.
/// Returns an error if the data item is not found.
pub fn get_data_item(&self, name: &str) -> Result<&DataItem, RuntimeError> {
debug!("Getting data item '{}'", name);
self.values
.get(name)
.ok_or(RuntimeError::DataItemNotDeclared)
Expand Down Expand Up @@ -173,10 +174,10 @@ impl Context {

/// Declares a new variable.
pub fn declare_variable(&mut self, name: &str) -> Result<(), RuntimeError> {
debug!("Declaring variable '{}'", name);
if self.values.contains_key(name) {
Err(RuntimeError::DataItemAlreadyDeclared)
} else {
debug!("Declaring variable '{}'", name);
self.values
.insert(name.to_string(), DataItem::new(DataType::Variable));
Ok(())
Expand All @@ -185,11 +186,11 @@ impl Context {

/// Declares a new signal.
pub fn declare_signal(&mut self, name: &str) -> Result<u32, RuntimeError> {
debug!("Declaring signal '{}'", name);
let signal_id = self.generate_id();
if self.values.contains_key(name) {
Err(RuntimeError::DataItemAlreadyDeclared)
} else {
debug!("Declaring signal '{}'", name);
self.values
.insert(name.to_string(), DataItem::new(DataType::Signal));
self.set_data_item(name, DataContent::Scalar(signal_id))?;
Expand All @@ -200,11 +201,11 @@ impl Context {
/// Declares a new const value as a signal.
/// Sets the value of the signal to the given value. This being the signal id.
pub fn declare_const(&mut self, value: u32) -> Result<(), RuntimeError> {
debug!("Declaring const '{:?}'", value);
let const_name = value.to_string();
if self.values.contains_key(&const_name) {
Err(RuntimeError::DataItemAlreadyDeclared)
} else {
debug!("Declaring const '{}'", const_name);
self.values
.insert(const_name.clone(), DataItem::new(DataType::Signal));
self.set_data_item(&const_name, DataContent::Scalar(value))?;
Expand All @@ -214,14 +215,29 @@ impl Context {

/// Declares a new auto generated variable.
pub fn declare_auto_var(&mut self) -> Result<String, RuntimeError> {
let auto_var_name = format!("auto_var_{}", self.generate_id());
if self.values.contains_key(&auto_var_name) {
let auto_name = format!("auto_var_{}", self.generate_id());
debug!("Declaring auto generated variable '{}'", auto_name);
if self.values.contains_key(&auto_name) {
Err(RuntimeError::DataItemAlreadyDeclared)
} else {
debug!("Declaring auto generated variable '{}'", auto_var_name);
self.values
.insert(auto_var_name.clone(), DataItem::new(DataType::Variable));
Ok(auto_var_name)
.insert(auto_name.clone(), DataItem::new(DataType::Variable));
Ok(auto_name)
}
}

/// Declares a new auto generated signal.
pub fn declare_auto_signal(&mut self) -> Result<String, RuntimeError> {
let signal_id = self.generate_id();
let auto_name = format!("auto_signal_{}", signal_id);
debug!("Declaring auto generated signal '{}'", auto_name);
if self.values.contains_key(&auto_name) {
Err(RuntimeError::DataItemAlreadyDeclared)
} else {
self.values
.insert(auto_name.to_string(), DataItem::new(DataType::Signal));
self.set_data_item(&auto_name, DataContent::Scalar(signal_id))?;
Ok(auto_name)
}
}

Expand Down Expand Up @@ -301,7 +317,6 @@ impl DataItem {

/// Sets the content of the data item. Returns an error if the item is a signal and is already set.
pub fn set_content(&mut self, content: DataContent) -> Result<(), RuntimeError> {
debug!("Setting content {:?} - {:?}", self.data_type, content);
match self.data_type {
DataType::Signal if self.content.is_some() => Err(RuntimeError::SignalAlreadySet),
_ => {
Expand Down
35 changes: 18 additions & 17 deletions src/traverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use crate::circuit::{AGateType, ArithmeticCircuit};
use crate::execute::{execute_expression, execute_infix_op, execute_statement};
use crate::program::ProgramError;
use crate::runtime::{DataType, Runtime};
use crate::runtime::{DataContent, DataType, Runtime};
use circom_circom_algebra::num_traits::ToPrimitive;
use circom_program_structure::ast::{
Access, Expression, ExpressionInfixOpcode, Statement, VariableType,
Expand Down Expand Up @@ -145,7 +145,7 @@ pub fn traverse_statement(
}
}

/// Examines an expression to determine its structure and dependencies before execution.
/// Process an expression and returns a name of a variable that contains the result.
pub fn traverse_expression(
ac: &mut ArithmeticCircuit,
runtime: &mut Runtime,
Expand Down Expand Up @@ -173,19 +173,15 @@ pub fn traverse_expression(
} => {
let ctx = runtime.get_current_context()?;

//TODO: for generic handling we should generate a name for an intermediate expression, we could ideally use only the values returned
// TODO: for generic handling we should generate a name for an intermediate expression, we could ideally use only the values returned
// Not possible with the current structure of traverse_expression
let varlhs = ctx.declare_auto_var()?;
let varrhs = ctx.declare_auto_var()?;

let varlop = traverse_expression(ac, runtime, &varlhs, lhe, _program_archive)?;
let varrop = traverse_expression(ac, runtime, &varrhs, rhe, _program_archive)?;

let res = traverse_infix_op(ac, runtime, var, &varlop, &varrop, infix_op)?;

match res {
Some(value) => Ok(value.to_string()),
None => Ok(var.to_string()),
}
traverse_infix_op(ac, runtime, &varlop, &varrop, infix_op)
}
Expression::Variable { name, access, .. } => {
let mut name_access = String::from(name);
Expand Down Expand Up @@ -256,11 +252,10 @@ pub fn traverse_expression(
pub fn traverse_infix_op(
ac: &mut ArithmeticCircuit,
runtime: &mut Runtime,
output: &str,
input_lhs: &str,
input_rhs: &str,
infixop: &ExpressionInfixOpcode,
) -> Result<Option<u32>, ProgramError> {
) -> Result<String, ProgramError> {
debug!("Traversing infix op");

let ctx = runtime.get_current_context()?;
Expand All @@ -275,18 +270,24 @@ pub fn traverse_infix_op(

// If both items are scalars we can directly execute.
if lhs.get_data_type() == DataType::Variable && rhs.get_data_type() == DataType::Variable {
return Ok(Some(execute_infix_op(&lhs_val, &rhs_val, infixop)));
let out = ctx.declare_auto_var()?;
ctx.set_data_item(
&out,
DataContent::Scalar(execute_infix_op(&lhs_val, &rhs_val, infixop)),
)?;

return Ok(out);
}

// If they're not we construct the gate.
// TODO: Fix, this will fail if the output is not assigned/declared
let output_id = ctx.get_data_item(output)?.get_u32()?;

let gate_type = AGateType::from(infixop);

ac.add_gate(output, output_id, lhs_val, rhs_val, gate_type);
let out = ctx.declare_auto_signal()?;
let output_id = ctx.get_data_item(&out)?.get_u32()?;

ac.add_gate(&out, output_id, lhs_val, rhs_val, gate_type);

Ok(None)
Ok(out)
}

/// Handles declaration of signals and variables
Expand Down

0 comments on commit 9346327

Please sign in to comment.