From 50072214bf097c3ae1b9e3e755bc5fa33c5f6e5a Mon Sep 17 00:00:00 2001 From: tohrnii <100405913+tohrnii@users.noreply.github.com> Date: Sat, 10 Dec 2022 10:15:04 +0000 Subject: [PATCH 1/5] test: add trace col group tests and refactor old tests --- parser/src/parser/tests/arithmetic_ops.rs | 2 ++ parser/src/parser/tests/trace_columns.rs | 14 ++++++++++++++ parser/src/parser/tests/transition_constraints.rs | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/parser/src/parser/tests/arithmetic_ops.rs b/parser/src/parser/tests/arithmetic_ops.rs index 3f7c3fde..7b902a80 100644 --- a/parser/src/parser/tests/arithmetic_ops.rs +++ b/parser/src/parser/tests/arithmetic_ops.rs @@ -1,3 +1,5 @@ +use crate::ast::TraceColAccess; + use super::{ build_parse_test, Identifier, Source, SourceSection::*, TransitionConstraint, TransitionExpr::*, TransitionStmt::*, diff --git a/parser/src/parser/tests/trace_columns.rs b/parser/src/parser/tests/trace_columns.rs index f10df251..53349c28 100644 --- a/parser/src/parser/tests/trace_columns.rs +++ b/parser/src/parser/tests/trace_columns.rs @@ -1,6 +1,14 @@ +<<<<<<< HEAD use super::{ build_parse_test, Error, Identifier, ParseError, Source, SourceSection::*, Trace, TraceAccess, TraceCols, TransitionConstraint, TransitionExpr::*, TransitionStmt::*, +======= +use crate::ast::TraceColAccess; + +use super::{ + build_parse_test, Error, Identifier, ParseError, Source, SourceSection::*, TraceCol, TraceCols, + TransitionConstraint, TransitionExpr::*, TransitionStmt::*, +>>>>>>> 8197516 (test: add trace col group tests and refactor old tests) }; // TRACE COLUMNS @@ -13,9 +21,15 @@ fn trace_columns() { main: [clk, fmp, ctx]"; let expected = Source(vec![Trace(Trace { main_cols: vec![ +<<<<<<< HEAD TraceCols::new(Identifier("clk".to_string()), 1), TraceCols::new(Identifier("fmp".to_string()), 1), TraceCols::new(Identifier("ctx".to_string()), 1), +======= + TraceCol::Single(Identifier("clk".to_string())), + TraceCol::Single(Identifier("fmp".to_string())), + TraceCol::Single(Identifier("ctx".to_string())), +>>>>>>> 8197516 (test: add trace col group tests and refactor old tests) ], aux_cols: vec![], })]); diff --git a/parser/src/parser/tests/transition_constraints.rs b/parser/src/parser/tests/transition_constraints.rs index 2aa9fe37..8a55ff86 100644 --- a/parser/src/parser/tests/transition_constraints.rs +++ b/parser/src/parser/tests/transition_constraints.rs @@ -46,7 +46,11 @@ fn multiple_transition_constraints() { enf clk' - clk = 1"; let expected = Source(vec![SourceSection::TransitionConstraints(vec![ Constraint(TransitionConstraint::new( +<<<<<<< HEAD Next(TraceAccess::new(Identifier("clk".to_string()), 0)), +======= + Next(TraceColAccess::Single(Identifier("clk".to_string()))), +>>>>>>> 8197516 (test: add trace col group tests and refactor old tests) Add( Box::new(Elem(Identifier("clk".to_string()))), Box::new(Const(1)), @@ -54,7 +58,11 @@ fn multiple_transition_constraints() { )), Constraint(TransitionConstraint::new( Sub( +<<<<<<< HEAD Box::new(Next(TraceAccess::new(Identifier("clk".to_string()), 0))), +======= + Box::new(Next(TraceColAccess::Single(Identifier("clk".to_string())))), +>>>>>>> 8197516 (test: add trace col group tests and refactor old tests) Box::new(Elem(Identifier("clk".to_string()))), ), Const(1), From c036551ce622abd09266d8e0af173e75359125d2 Mon Sep 17 00:00:00 2001 From: tohrnii <100405913+tohrnii@users.noreply.github.com> Date: Fri, 16 Dec 2022 05:15:14 +0000 Subject: [PATCH 2/5] refactor(parser): refactor trace columns AST --- parser/src/parser/tests/arithmetic_ops.rs | 2 -- parser/src/parser/tests/trace_columns.rs | 14 -------------- parser/src/parser/tests/transition_constraints.rs | 8 -------- 3 files changed, 24 deletions(-) diff --git a/parser/src/parser/tests/arithmetic_ops.rs b/parser/src/parser/tests/arithmetic_ops.rs index 7b902a80..3f7c3fde 100644 --- a/parser/src/parser/tests/arithmetic_ops.rs +++ b/parser/src/parser/tests/arithmetic_ops.rs @@ -1,5 +1,3 @@ -use crate::ast::TraceColAccess; - use super::{ build_parse_test, Identifier, Source, SourceSection::*, TransitionConstraint, TransitionExpr::*, TransitionStmt::*, diff --git a/parser/src/parser/tests/trace_columns.rs b/parser/src/parser/tests/trace_columns.rs index 53349c28..f10df251 100644 --- a/parser/src/parser/tests/trace_columns.rs +++ b/parser/src/parser/tests/trace_columns.rs @@ -1,14 +1,6 @@ -<<<<<<< HEAD use super::{ build_parse_test, Error, Identifier, ParseError, Source, SourceSection::*, Trace, TraceAccess, TraceCols, TransitionConstraint, TransitionExpr::*, TransitionStmt::*, -======= -use crate::ast::TraceColAccess; - -use super::{ - build_parse_test, Error, Identifier, ParseError, Source, SourceSection::*, TraceCol, TraceCols, - TransitionConstraint, TransitionExpr::*, TransitionStmt::*, ->>>>>>> 8197516 (test: add trace col group tests and refactor old tests) }; // TRACE COLUMNS @@ -21,15 +13,9 @@ fn trace_columns() { main: [clk, fmp, ctx]"; let expected = Source(vec![Trace(Trace { main_cols: vec![ -<<<<<<< HEAD TraceCols::new(Identifier("clk".to_string()), 1), TraceCols::new(Identifier("fmp".to_string()), 1), TraceCols::new(Identifier("ctx".to_string()), 1), -======= - TraceCol::Single(Identifier("clk".to_string())), - TraceCol::Single(Identifier("fmp".to_string())), - TraceCol::Single(Identifier("ctx".to_string())), ->>>>>>> 8197516 (test: add trace col group tests and refactor old tests) ], aux_cols: vec![], })]); diff --git a/parser/src/parser/tests/transition_constraints.rs b/parser/src/parser/tests/transition_constraints.rs index 8a55ff86..2aa9fe37 100644 --- a/parser/src/parser/tests/transition_constraints.rs +++ b/parser/src/parser/tests/transition_constraints.rs @@ -46,11 +46,7 @@ fn multiple_transition_constraints() { enf clk' - clk = 1"; let expected = Source(vec![SourceSection::TransitionConstraints(vec![ Constraint(TransitionConstraint::new( -<<<<<<< HEAD Next(TraceAccess::new(Identifier("clk".to_string()), 0)), -======= - Next(TraceColAccess::Single(Identifier("clk".to_string()))), ->>>>>>> 8197516 (test: add trace col group tests and refactor old tests) Add( Box::new(Elem(Identifier("clk".to_string()))), Box::new(Const(1)), @@ -58,11 +54,7 @@ fn multiple_transition_constraints() { )), Constraint(TransitionConstraint::new( Sub( -<<<<<<< HEAD Box::new(Next(TraceAccess::new(Identifier("clk".to_string()), 0))), -======= - Box::new(Next(TraceColAccess::Single(Identifier("clk".to_string())))), ->>>>>>> 8197516 (test: add trace col group tests and refactor old tests) Box::new(Elem(Identifier("clk".to_string()))), ), Const(1), From 04028356bad62ac75e31942aa418b64895323de3 Mon Sep 17 00:00:00 2001 From: tohrnii <100405913+tohrnii@users.noreply.github.com> Date: Wed, 14 Dec 2022 06:34:19 +0000 Subject: [PATCH 3/5] feat(ir): add support for trace col groups to IR --- ir/src/boundary_constraints.rs | 34 ++++++++++++++++++ ir/src/lib.rs | 8 +++++ ir/src/symbol_table.rs | 21 ++++++++++- ir/src/trace_column.rs | 61 ++++++++++++++++++++++++++++++++ ir/src/trace_columns.rs | 39 -------------------- ir/src/transition_stmts/graph.rs | 56 +++++++++++++++++++++-------- 6 files changed, 165 insertions(+), 54 deletions(-) create mode 100644 ir/src/trace_column.rs delete mode 100644 ir/src/trace_columns.rs diff --git a/ir/src/boundary_constraints.rs b/ir/src/boundary_constraints.rs index b283be98..7872a58a 100644 --- a/ir/src/boundary_constraints.rs +++ b/ir/src/boundary_constraints.rs @@ -92,6 +92,40 @@ impl BoundaryConstraints { }, _ => unimplemented!(), }, + IdentifierType::TraceColumnGroup(column_group) => { + if let TraceColAccess::GroupAccess(name, idx) = constraint.column() { + if *idx >= column_group.size() { + return Err(SemanticError::vector_access_out_of_bounds( + &VectorAccess::new(name.clone(), *idx), + column_group.size(), + )); + } + match column_group.trace_segment() { + 0 => match constraint.boundary() { + ast::Boundary::First => self + .main_first + .insert(column_group.start_col_idx() + idx, expr), + ast::Boundary::Last => self + .main_last + .insert(column_group.start_col_idx() + idx, expr), + }, + 1 => match constraint.boundary() { + ast::Boundary::First => self + .aux_first + .insert(column_group.start_col_idx() + idx, expr), + ast::Boundary::Last => self + .aux_last + .insert(column_group.start_col_idx() + idx, expr), + }, + _ => unimplemented!(), + } + } else { + return Err(SemanticError::InvalidUsage(format!( + "Identifier {} was declared as a {}, not as a trace column group", + col_name, col_type + ))); + } + } _ => { return Err(SemanticError::InvalidUsage(format!( "Identifier {} was declared as a {}, not as a trace column", diff --git a/ir/src/lib.rs b/ir/src/lib.rs index 21187bc4..e29759ee 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -2,6 +2,11 @@ pub use parser::ast::{ self, boundary_constraints::BoundaryExpr, constants::Constant, Identifier, PublicInput, TransitionVariable, }; +<<<<<<< HEAD +======= +use parser::ast::{BoundaryStmt, TransitionStmt}; +use trace_column::TraceColumnGroup; +>>>>>>> 41eb6b1 (feat(ir): add support for trace col groups to IR) use std::collections::BTreeMap; mod symbol_table; @@ -14,6 +19,8 @@ pub mod transition_stmts; use transition_stmts::{AlgebraicGraph, TransitionStmts, VariableValue, MIN_CYCLE_LENGTH}; pub use transition_stmts::{NodeIndex, TransitionConstraintDegree}; +mod trace_column; + mod error; use error::SemanticError; @@ -29,6 +36,7 @@ pub type PublicInputs = Vec<(String, usize)>; pub type PeriodicColumns = Vec>; pub type BoundaryConstraintsMap = BTreeMap; pub type VariableRoots = BTreeMap; +pub type TraceColumnGroups = BTreeMap; /// Internal representation of an AIR. /// diff --git a/ir/src/symbol_table.rs b/ir/src/symbol_table.rs index 56ced535..e189783b 100644 --- a/ir/src/symbol_table.rs +++ b/ir/src/symbol_table.rs @@ -1,6 +1,7 @@ use super::{ + trace_column::{TraceColumn, TraceColumnGroup}, BTreeMap, Constants, PeriodicColumns, PublicInputs, SemanticError, TraceSegment, - MIN_CYCLE_LENGTH, + TraceColumnGroups, MIN_CYCLE_LENGTH, }; use parser::ast::{ constants::{Constant, ConstantType}, @@ -16,6 +17,7 @@ pub(super) enum IdentifierType { /// an identifier for a trace column, containing trace column information with its trace segment /// and the index of the column in that segment. TraceColumn(TraceColumn), + TraceColumnGroup(TraceColumnGroup), /// an identifier for a public input, containing the size of the public input array PublicInput(usize), /// an identifier for a periodic column, containing its index out of all periodic columns and @@ -35,6 +37,13 @@ impl Display for IdentifierType { write!(f, "TraceColumn in segment {}", column.trace_segment()) } Self::TransitionVariable(_) => write!(f, "TransitionVariable"), + Self::TraceColumnGroup(column_group) => { + write!( + f, + "TraceColumnGroup in segment {}", + column_group.trace_segment() + ) + } } } } @@ -262,6 +271,16 @@ impl SymbolTable { )) } } + IdentifierType::TraceColumnGroup(trace_column_group) => { + if vector_access.idx() < trace_column_group.size() { + Ok(symbol_type) + } else { + Err(SemanticError::vector_access_out_of_bounds( + vector_access, + trace_column_group.size(), + )) + } + } _ => Err(SemanticError::invalid_vector_access( vector_access, symbol_type, diff --git a/ir/src/trace_column.rs b/ir/src/trace_column.rs new file mode 100644 index 00000000..643a8b43 --- /dev/null +++ b/ir/src/trace_column.rs @@ -0,0 +1,61 @@ +use super::TraceSegment; + +/// Describes a column in the execution trace by the trace segment to which it belongs and its +/// index within that segment. +#[derive(Debug, Copy, Clone)] +pub struct TraceColumn { + trace_segment: TraceSegment, + col_idx: usize, +} + +impl TraceColumn { + /// Creates a [TraceColumn] in the specified trace segment at the specified index. + pub fn new(trace_segment: TraceSegment, col_idx: usize) -> Self { + Self { + trace_segment, + col_idx, + } + } + + /// Gets the trace segment of this [TraceColumn]. + pub fn trace_segment(&self) -> TraceSegment { + self.trace_segment + } + + /// Gets the column index of this [TraceColumn]. + pub fn col_idx(&self) -> usize { + self.col_idx + } +} + +#[derive(Debug, Clone)] +pub struct TraceColumnGroup { + trace_segment: TraceSegment, + size: usize, + start_col_idx: usize, +} + +impl TraceColumnGroup { + /// Creates a [TraceColumnGroup] in the specified trace segment at the specified start index. + pub fn new(trace_segment: TraceSegment, size: usize, start_col_idx: usize) -> Self { + Self { + trace_segment, + size, + start_col_idx, + } + } + + /// Gets the trace segment of this [TraceColumn]. + pub fn trace_segment(&self) -> TraceSegment { + self.trace_segment + } + + pub fn size(&self) -> usize { + self.size + } + + /// Gets the start column index of this [TraceColumn]. + pub fn start_col_idx(&self) -> usize { + self.start_col_idx + } +} \ No newline at end of file diff --git a/ir/src/trace_columns.rs b/ir/src/trace_columns.rs deleted file mode 100644 index 8846c0f7..00000000 --- a/ir/src/trace_columns.rs +++ /dev/null @@ -1,39 +0,0 @@ -use super::{BTreeMap, SemanticError}; - -/// A representation of the trace columns declared for the AIR. -#[derive(Debug, Default)] -pub struct TraceColumns { - /// A map of a set of trace columns using the declared identifier as the key and the column - /// index as the value. - columns: BTreeMap, -} - -impl TraceColumns { - /// Add a new column by its name and index - pub(super) fn insert(&mut self, name: &str, index: usize) -> Result<(), SemanticError> { - let result = self.columns.insert(name.to_string(), index); - if result.is_some() { - Err(SemanticError::DuplicateTraceColumn(format!( - "{} was defined more than once", - name - ))) - } else { - Ok(()) - } - } - - /// Returns the index in the trace of the column with the specified name. - /// - /// # Errors - /// Returns an error if the column name identifier is not recognized as a valid trace column. - pub(crate) fn get_column_index(&self, name: &str) -> Result { - if let Some(&index) = self.columns.get(name) { - Ok(index) - } else { - Err(SemanticError::InvalidIdentifier(format!( - "Trace column {} was not declared", - name, - ))) - } - } -} diff --git a/ir/src/transition_stmts/graph.rs b/ir/src/transition_stmts/graph.rs index 106f394c..8a094245 100644 --- a/ir/src/transition_stmts/graph.rs +++ b/ir/src/transition_stmts/graph.rs @@ -5,6 +5,7 @@ use crate::{symbol_table::IdentifierType, VariableRoots}; use parser::ast::{ constants::ConstantType, Identifier, MatrixAccess, TransitionExpr, TransitionVariableType, VectorAccess, + self, constants::ConstantType, Identifier, MatrixAccess, TransitionExpr, VectorAccess, }; // ALGEBRAIC GRAPH @@ -109,7 +110,7 @@ impl AlgebraicGraph { self.insert_matrix_access(symbol_table, &matrix_access, variable_roots) } TransitionExpr::Next(trace_access) => { - self.insert_next(symbol_table, trace_access.name()) + self.insert_next(symbol_table, &trace_access) } TransitionExpr::Rand(index) => { // constraint target for random values defaults to the second trace segment. @@ -164,21 +165,38 @@ impl AlgebraicGraph { fn insert_next( &mut self, symbol_table: &SymbolTable, - ident: &str, + trace_col_access: &ast::TraceAccess, ) -> Result<(TraceSegment, NodeIndex), SemanticError> { - let col_type = symbol_table.get_type(ident)?; - - match col_type { - IdentifierType::TraceColumn(column) => { - let trace_segment = column.trace_segment(); - let trace_access = TraceAccess::new(trace_segment, column.col_idx(), 1); - let node_index = self.insert_op(Operation::TraceElement(trace_access)); - Ok((trace_segment, node_index)) + match trace_col_access { + TraceColAccess::Single(ident) => { + let col_type = symbol_table.get_type(ident.name())?; + if let IdentifierType::TraceColumn(column) = col_type { + let trace_segment = column.trace_segment(); + let trace_access = TraceAccess::new(trace_segment, column.col_idx(), 1); + let node_index = self.insert_op(Operation::TraceElement(trace_access)); + Ok((trace_segment, node_index)) + } else { + Err(SemanticError::InvalidUsage(format!( + "Identifier {} was declared as a {} not as a trace column", + ident, col_type + ))) + } + } + TraceColAccess::GroupAccess(ident, idx) => { + let col_type = symbol_table.get_type(ident.name())?; + if let IdentifierType::TraceColumnGroup(column_group) = col_type { + let trace_segment = column_group.trace_segment(); + let trace_access = + TraceAccess::new(trace_segment, idx + column_group.start_col_idx(), 1); + let node_index = self.insert_op(Operation::TraceElement(trace_access)); + Ok((trace_segment, node_index)) + } else { + Err(SemanticError::InvalidUsage(format!( + "Identifier {} was declared as a {} not as a trace column group", + ident, col_type + ))) + } } - _ => Err(SemanticError::InvalidUsage(format!( - "Identifier {} was declared as a {} not as a trace column", - ident, col_type - ))), } } @@ -287,6 +305,16 @@ impl AlgebraicGraph { ))) } } + IdentifierType::TraceColumnGroup(trace_column_group) => { + let trace_segment = trace_column_group.trace_segment(); + let col_idx = trace_column_group.start_col_idx() + vector_access.idx(); + let node_index = self.insert_op(Operation::TraceElement(TraceAccess::new( + trace_segment, + col_idx, + 0, + ))); + Ok((trace_segment, node_index)) + } _ => Err(SemanticError::invalid_vector_access( vector_access, symbol_type, From c13bb22be445b66acf7ee185be8f103262ace988 Mon Sep 17 00:00:00 2001 From: tohrnii <100405913+tohrnii@users.noreply.github.com> Date: Wed, 14 Dec 2022 06:34:46 +0000 Subject: [PATCH 4/5] test: add tests for trace column groups to IR --- ir/src/tests/mod.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/ir/src/tests/mod.rs b/ir/src/tests/mod.rs index d8e8cc65..bd153769 100644 --- a/ir/src/tests/mod.rs +++ b/ir/src/tests/mod.rs @@ -40,6 +40,73 @@ fn boundary_constraints_with_constants() { assert!(result.is_ok()); } +#[test] +fn trace_cols_groups() { + let source = " + constants: + A: 123 + B: [1, 2, 3] + C: [[1, 2, 3], [4, 5, 6]] + trace_columns: + main: [clk, a[4]] + public_inputs: + stack_inputs: [16] + transition_constraints: + enf a[0]' = a[1] - 1 + boundary_constraints: + enf a[1].first = A + enf clk.last = B[0] + C[0][1]"; + + let parsed = parse(source).expect("Parsing failed"); + let result = AirIR::from_source(&parsed); + assert!(result.is_ok()); +} + +#[test] +fn err_trace_cols_access_out_of_bounds() { + // out of bounds in transition constraints + let source = " + constants: + A: 123 + B: [1, 2, 3] + C: [[1, 2, 3], [4, 5, 6]] + trace_columns: + main: [clk, a[4]] + public_inputs: + stack_inputs: [16] + transition_constraints: + enf a[4]' = a[4] - 1 + boundary_constraints: + enf a[1].first = A + enf clk.last = B[0] + C[0][1]"; + + let parsed = parse(source).expect("Parsing failed"); + + let result = AirIR::from_source(&parsed); + assert!(result.is_err()); + + // out of bounds in boundary constraints + let source = " + constants: + A: 123 + B: [1, 2, 3] + C: [[1, 2, 3], [4, 5, 6]] + trace_columns: + main: [clk, a[4]] + public_inputs: + stack_inputs: [16] + transition_constraints: + enf a[0]' = a[0] - 1 + boundary_constraints: + enf a[4].first = A + enf clk.last = B[0] + C[0][1]"; + + let parsed = parse(source).expect("Parsing failed"); + + let result = AirIR::from_source(&parsed); + assert!(result.is_err()); +} + #[test] fn err_tc_invalid_vector_access() { let source = " From 2fdc6f1c9ebf63ba4cec6ec9894d5882f1ad1541 Mon Sep 17 00:00:00 2001 From: tohrnii <100405913+tohrnii@users.noreply.github.com> Date: Wed, 14 Dec 2022 06:35:03 +0000 Subject: [PATCH 5/5] test: add integration test for trace column groups --- air-script/tests/main.rs | 10 + .../trace_col_groups/trace_col_groups.air | 15 ++ .../trace_col_groups/trace_col_groups.rs | 89 +++++++++ ir/src/boundary_constraints.rs | 176 ------------------ ir/src/boundary_stmts.rs | 28 ++- ir/src/error.rs | 11 +- ir/src/lib.rs | 15 +- ir/src/symbol_table.rs | 67 ++----- ir/src/tests/mod.rs | 22 +-- ir/src/trace_column.rs | 61 ------ ir/src/trace_columns.rs | 36 ++++ ir/src/transition_stmts/graph.rs | 72 +++---- parser/src/lexer/mod.rs | 2 +- parser/src/parser/grammar.lalrpop | 2 +- 14 files changed, 243 insertions(+), 363 deletions(-) create mode 100644 air-script/tests/trace_col_groups/trace_col_groups.air create mode 100644 air-script/tests/trace_col_groups/trace_col_groups.rs delete mode 100644 ir/src/boundary_constraints.rs delete mode 100644 ir/src/trace_column.rs create mode 100644 ir/src/trace_columns.rs diff --git a/air-script/tests/main.rs b/air-script/tests/main.rs index d096ecd0..ad1a8e90 100644 --- a/air-script/tests/main.rs +++ b/air-script/tests/main.rs @@ -85,3 +85,13 @@ fn variables() { let expected = expect_file!["variables/variables.rs"]; expected.assert_eq(&generated_air); } + +#[test] +fn trace_col_groups() { + let generated_air = Test::new("tests/trace_col_groups/trace_col_groups.air".to_string()) + .transpile() + .unwrap(); + + let expected = expect_file!["trace_col_groups/trace_col_groups.rs"]; + expected.assert_eq(&generated_air); +} diff --git a/air-script/tests/trace_col_groups/trace_col_groups.air b/air-script/tests/trace_col_groups/trace_col_groups.air new file mode 100644 index 00000000..1dd8f0fc --- /dev/null +++ b/air-script/tests/trace_col_groups/trace_col_groups.air @@ -0,0 +1,15 @@ +def TraceColGroupAir + +trace_columns: + main: [clk, fmp[2], ctx] + aux: [a, b, c[3]] + +public_inputs: + stack_inputs: [16] + +transition_constraints: + enf fmp[1]' = fmp[1] + 1 + enf fmp[0]' = fmp[0] - 1 + +boundary_constraints: + enf c[2].first = 0 \ No newline at end of file diff --git a/air-script/tests/trace_col_groups/trace_col_groups.rs b/air-script/tests/trace_col_groups/trace_col_groups.rs new file mode 100644 index 00000000..45be4339 --- /dev/null +++ b/air-script/tests/trace_col_groups/trace_col_groups.rs @@ -0,0 +1,89 @@ +use winter_air::{Air, AirContext, Assertion, AuxTraceRandElements, EvaluationFrame, ProofOptions as WinterProofOptions, TransitionConstraintDegree, TraceInfo}; +use winter_math::fields::f64::BaseElement as Felt; +use winter_math::{ExtensionOf, FieldElement}; +use winter_utils::collections::Vec; +use winter_utils::{ByteWriter, Serializable}; + +pub struct PublicInputs { + stack_inputs: [Felt; 16], +} + +impl PublicInputs { + pub fn new(stack_inputs: [Felt; 16]) -> Self { + Self { stack_inputs } + } +} + +impl Serializable for PublicInputs { + fn write_into(&self, target: &mut W) { + target.write(self.stack_inputs.as_slice()); + } +} + +pub struct TraceColGroupAir { + context: AirContext, + stack_inputs: [Felt; 16], +} + +impl TraceColGroupAir { + pub fn last_step(&self) -> usize { + self.trace_length() - self.context().num_transition_exemptions() + } +} + +impl Air for TraceColGroupAir { + type BaseField = Felt; + type PublicInputs = PublicInputs; + + fn context(&self) -> &AirContext { + &self.context + } + + fn new(trace_info: TraceInfo, public_inputs: PublicInputs, options: WinterProofOptions) -> Self { + let main_degrees = vec![TransitionConstraintDegree::new(1), TransitionConstraintDegree::new(1)]; + let aux_degrees = vec![]; + let num_main_assertions = 0; + let num_aux_assertions = 1; + + let context = AirContext::new_multi_segment( + trace_info, + main_degrees, + aux_degrees, + num_main_assertions, + num_aux_assertions, + options, + ) + .set_num_transition_exemptions(2); + Self { context, stack_inputs: public_inputs.stack_inputs } + } + + fn get_periodic_column_values(&self) -> Vec> { + vec![] + } + + fn get_assertions(&self) -> Vec> { + let mut result = Vec::new(); + result + } + + fn get_aux_assertions>(&self, aux_rand_elements: &AuxTraceRandElements) -> Vec> { + let mut result = Vec::new(); + result.push(Assertion::single(4, 0, E::from(0_u64))); + result + } + + fn evaluate_transition>(&self, frame: &EvaluationFrame, periodic_values: &[E], result: &mut [E]) { + let current = frame.current(); + let next = frame.next(); + result[0] = next[2] - (current[2] + E::from(1_u64)); + result[1] = next[1] - (current[1] - (E::from(1_u64))); + } + + fn evaluate_aux_transition(&self, main_frame: &EvaluationFrame, aux_frame: &EvaluationFrame, _periodic_values: &[F], aux_rand_elements: &AuxTraceRandElements, result: &mut [E]) + where F: FieldElement, + E: FieldElement + ExtensionOf, + { + let current = aux_frame.current(); + let next = aux_frame.next(); + } +} \ No newline at end of file diff --git a/ir/src/boundary_constraints.rs b/ir/src/boundary_constraints.rs deleted file mode 100644 index 7872a58a..00000000 --- a/ir/src/boundary_constraints.rs +++ /dev/null @@ -1,176 +0,0 @@ -use super::{BTreeMap, BoundaryExpr, IdentifierType, SemanticError, SymbolTable}; -use parser::ast; - -// BOUNDARY CONSTRAINTS -// ================================================================================================ - -/// A struct containing all of the boundary constraints to be applied at each of the 2 allowed -/// boundaries (first row and last row). For ease of code generation and evaluation, constraints are -/// sorted into maps by the boundary. This also simplifies ensuring that there are no conflicting -/// constraints sharing a boundary and column index. -/// TODO: generalize the way we store boundary constraints for more trace segments. -#[derive(Default, Debug)] -pub(crate) struct BoundaryConstraints { - /// The boundary constraints to be applied at the first row of the main trace, with the trace - /// column index as the key, and the expression as the value. - main_first: BTreeMap, - /// The boundary constraints to be applied at the last row of the main trace, with the trace - /// column index as the key, and the expression as the value. - main_last: BTreeMap, - /// The boundary constraints to be applied at the first row of the aux trace, with the trace - /// column index as the key, and the expression as the value. - aux_first: BTreeMap, - /// The boundary constraints to be applied at the last row of the aux trace, with the trace - /// column index as the key, and the expression as the value. - aux_last: BTreeMap, -} - -impl BoundaryConstraints { - // --- ACCESSORS ------------------------------------------------------------------------------ - - /// Returns the total number of boundary constraints for the main trace. - pub fn main_len(&self) -> usize { - self.main_first.len() + self.main_last.len() - } - - /// Returns all of the boundary constraints for the first row of the main trace. - pub fn main_first(&self) -> Vec<(usize, &BoundaryExpr)> { - self.main_first.iter().map(|(k, v)| (*k, v)).collect() - } - - /// Returns all of the boundary constraints for the final row of the main trace. - pub fn main_last(&self) -> Vec<(usize, &BoundaryExpr)> { - self.main_last.iter().map(|(k, v)| (*k, v)).collect() - } - - /// Returns the total number of boundary constraints for the aux trace. - pub fn aux_len(&self) -> usize { - self.aux_first.len() + self.aux_last.len() - } - - /// Returns all of the boundary constraints for the first row of the aux trace. - pub fn aux_first(&self) -> Vec<(usize, &BoundaryExpr)> { - self.aux_first.iter().map(|(k, v)| (*k, v)).collect() - } - - /// Returns all of the boundary constraints for the final row of the aux trace. - pub fn aux_last(&self) -> Vec<(usize, &BoundaryExpr)> { - self.aux_last.iter().map(|(k, v)| (*k, v)).collect() - } - - // --- MUTATORS ------------------------------------------------------------------------------- - - /// Add a boundary constraint from the AST to the list of constraints for its specified - /// boundary. - /// - /// # Errors - /// Returns an error if: - /// - The identifier specified for the boundary constraint column has not been declared or has - /// been declared with the wrong type. - /// - The constraint expression is contains invalid public input references. - /// - A boundary constraint has already been declared for the specified column and boundary. - pub(super) fn insert( - &mut self, - symbol_table: &SymbolTable, - constraint: &ast::BoundaryConstraint, - ) -> Result<(), SemanticError> { - // validate the expression - let expr = constraint.value(); - validate_expression(symbol_table, &expr)?; - - // add the constraint to the specified boundary for the specified trace - let col_type = symbol_table.get_type(constraint.column().name())?; - let result = match col_type { - IdentifierType::TraceColumn(column) => match column.trace_segment() { - 0 => match constraint.boundary() { - ast::Boundary::First => self.main_first.insert(column.col_idx(), expr), - ast::Boundary::Last => self.main_last.insert(column.col_idx(), expr), - }, - 1 => match constraint.boundary() { - ast::Boundary::First => self.aux_first.insert(column.col_idx(), expr), - ast::Boundary::Last => self.aux_last.insert(column.col_idx(), expr), - }, - _ => unimplemented!(), - }, - IdentifierType::TraceColumnGroup(column_group) => { - if let TraceColAccess::GroupAccess(name, idx) = constraint.column() { - if *idx >= column_group.size() { - return Err(SemanticError::vector_access_out_of_bounds( - &VectorAccess::new(name.clone(), *idx), - column_group.size(), - )); - } - match column_group.trace_segment() { - 0 => match constraint.boundary() { - ast::Boundary::First => self - .main_first - .insert(column_group.start_col_idx() + idx, expr), - ast::Boundary::Last => self - .main_last - .insert(column_group.start_col_idx() + idx, expr), - }, - 1 => match constraint.boundary() { - ast::Boundary::First => self - .aux_first - .insert(column_group.start_col_idx() + idx, expr), - ast::Boundary::Last => self - .aux_last - .insert(column_group.start_col_idx() + idx, expr), - }, - _ => unimplemented!(), - } - } else { - return Err(SemanticError::InvalidUsage(format!( - "Identifier {} was declared as a {}, not as a trace column group", - col_name, col_type - ))); - } - } - _ => { - return Err(SemanticError::InvalidUsage(format!( - "Identifier {} was declared as a {}, not as a trace column", - constraint.column().name(), - col_type - ))); - } - }; - - // raise an error if multiple constraints were applied to the same boundary - if result.is_some() { - return Err(SemanticError::TooManyConstraints(format!( - "A boundary constraint was already defined for {} '{}' at the {}", - col_type, - constraint.column().name(), - constraint.boundary() - ))); - } - - Ok(()) - } -} - -/// Recursively validates the BoundaryExpression. -/// -/// # Errors -/// Returns an error if the expression includes a reference to a public input that hasn't been -/// declared or to an invalid index in an existing public input. -fn validate_expression( - symbol_table: &SymbolTable, - expr: &ast::BoundaryExpr, -) -> Result<(), SemanticError> { - match expr { - BoundaryExpr::VectorAccess(vector_access) => { - symbol_table.access_vector_element(vector_access)?; - Ok(()) - } - BoundaryExpr::MatrixAccess(matrix_access) => { - symbol_table.access_matrix_element(matrix_access)?; - Ok(()) - } - BoundaryExpr::Add(lhs, rhs) | BoundaryExpr::Sub(lhs, rhs) => { - validate_expression(symbol_table, lhs)?; - validate_expression(symbol_table, rhs) - } - _ => Ok(()), - } -} diff --git a/ir/src/boundary_stmts.rs b/ir/src/boundary_stmts.rs index b7ead2a5..4bb81055 100644 --- a/ir/src/boundary_stmts.rs +++ b/ir/src/boundary_stmts.rs @@ -133,16 +133,24 @@ impl BoundaryStmts { // add the constraint to the specified boundary for the specified trace let col_type = symbol_table.get_type(constraint.column().name())?; let result = match col_type { - IdentifierType::TraceColumn(column) => match constraint.boundary() { - ast::Boundary::First => self.boundary_constraints - [column.trace_segment() as usize] - .first_mut() - .insert(column.col_idx(), expr), - ast::Boundary::Last => self.boundary_constraints - [column.trace_segment() as usize] - .last_mut() - .insert(column.col_idx(), expr), - }, + IdentifierType::TraceColumns(columns) => { + if constraint.column().idx() >= columns.size() { + return Err(SemanticError::trace_access_out_of_bounds( + constraint.column(), + columns.size(), + )); + } + match constraint.boundary() { + ast::Boundary::First => self.boundary_constraints + [columns.trace_segment() as usize] + .first_mut() + .insert(columns.offset() + constraint.column().idx(), expr), + ast::Boundary::Last => self.boundary_constraints + [columns.trace_segment() as usize] + .last_mut() + .insert(columns.offset() + constraint.column().idx(), expr), + } + } _ => { return Err(SemanticError::InvalidUsage(format!( "Identifier {} was declared as a {}, not as a trace column", diff --git a/ir/src/error.rs b/ir/src/error.rs index b4fe5864..5fa43066 100644 --- a/ir/src/error.rs +++ b/ir/src/error.rs @@ -1,5 +1,5 @@ use crate::symbol_table::IdentifierType; -use parser::ast::{MatrixAccess, VectorAccess}; +use parser::ast::{MatrixAccess, TraceAccess, VectorAccess}; #[derive(Debug)] pub enum SemanticError { @@ -49,6 +49,15 @@ impl SemanticError { )) } + pub(super) fn trace_access_out_of_bounds(access: &TraceAccess, size: usize) -> Self { + Self::IndexOutOfRange(format!( + "Out-of-range index {} in trace {} of length {}", + access.idx(), + access.name(), + size + )) + } + pub(super) fn public_inputs_out_of_bounds(access: &VectorAccess, size: usize) -> Self { SemanticError::IndexOutOfRange(format!( "Out-of-range index {} in public input {} of length {}", diff --git a/ir/src/lib.rs b/ir/src/lib.rs index e29759ee..7b21d22b 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -2,11 +2,6 @@ pub use parser::ast::{ self, boundary_constraints::BoundaryExpr, constants::Constant, Identifier, PublicInput, TransitionVariable, }; -<<<<<<< HEAD -======= -use parser::ast::{BoundaryStmt, TransitionStmt}; -use trace_column::TraceColumnGroup; ->>>>>>> 41eb6b1 (feat(ir): add support for trace col groups to IR) use std::collections::BTreeMap; mod symbol_table; @@ -19,7 +14,7 @@ pub mod transition_stmts; use transition_stmts::{AlgebraicGraph, TransitionStmts, VariableValue, MIN_CYCLE_LENGTH}; pub use transition_stmts::{NodeIndex, TransitionConstraintDegree}; -mod trace_column; +mod trace_columns; mod error; use error::SemanticError; @@ -30,13 +25,19 @@ use helpers::SourceValidator; #[cfg(test)] mod tests; +// ==== ALIASES =================================================================================== pub type TraceSegment = u8; pub type Constants = Vec; pub type PublicInputs = Vec<(String, usize)>; pub type PeriodicColumns = Vec>; pub type BoundaryConstraintsMap = BTreeMap; pub type VariableRoots = BTreeMap; -pub type TraceColumnGroups = BTreeMap; + +// ==== CONSTANTS ================================================================================= +const CURRENT_ROW: usize = 0; +const NEXT_ROW: usize = 1; + +// ==== AIR IR ==================================================================================== /// Internal representation of an AIR. /// diff --git a/ir/src/symbol_table.rs b/ir/src/symbol_table.rs index e189783b..8f35a445 100644 --- a/ir/src/symbol_table.rs +++ b/ir/src/symbol_table.rs @@ -1,7 +1,6 @@ use super::{ - trace_column::{TraceColumn, TraceColumnGroup}, - BTreeMap, Constants, PeriodicColumns, PublicInputs, SemanticError, TraceSegment, - TraceColumnGroups, MIN_CYCLE_LENGTH, + trace_columns::TraceColumns, BTreeMap, Constants, PeriodicColumns, PublicInputs, SemanticError, + TraceSegment, MIN_CYCLE_LENGTH, }; use parser::ast::{ constants::{Constant, ConstantType}, @@ -14,10 +13,9 @@ use std::fmt::Display; pub(super) enum IdentifierType { /// an identifier for a constant, containing it's type and value Constant(ConstantType), - /// an identifier for a trace column, containing trace column information with its trace segment - /// and the index of the column in that segment. - TraceColumn(TraceColumn), - TraceColumnGroup(TraceColumnGroup), + /// an identifier for a trace column, containing trace column information with its trace + /// segment, it's size and it's offset. + TraceColumns(TraceColumns), /// an identifier for a public input, containing the size of the public input array PublicInput(usize), /// an identifier for a periodic column, containing its index out of all periodic columns and @@ -33,49 +31,14 @@ impl Display for IdentifierType { Self::Constant(_) => write!(f, "Constant"), Self::PublicInput(_) => write!(f, "PublicInput"), Self::PeriodicColumn(_, _) => write!(f, "PeriodicColumn"), - Self::TraceColumn(column) => { - write!(f, "TraceColumn in segment {}", column.trace_segment()) + Self::TraceColumns(columns) => { + write!(f, "TraceColumns in segment {}", columns.trace_segment()) } Self::TransitionVariable(_) => write!(f, "TransitionVariable"), - Self::TraceColumnGroup(column_group) => { - write!( - f, - "TraceColumnGroup in segment {}", - column_group.trace_segment() - ) - } } } } -/// Describes a column in the execution trace by the trace segment to which it belongs and its -/// index within that segment. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct TraceColumn { - trace_segment: TraceSegment, - col_idx: usize, -} - -impl TraceColumn { - /// Creates a [TraceColumn] in the specified trace segment at the specified index. - fn new(trace_segment: TraceSegment, col_idx: usize) -> Self { - Self { - trace_segment, - col_idx, - } - } - - /// Gets the trace segment of this [TraceColumn]. - pub fn trace_segment(&self) -> TraceSegment { - self.trace_segment - } - - /// Gets the column index of this [TraceColumn]. - pub fn col_idx(&self) -> usize { - self.col_idx - } -} - /// SymbolTable for identifiers to track their types and information and enforce uniqueness of /// identifiers. #[derive(Default, Debug)] @@ -139,7 +102,7 @@ impl SymbolTable { Ok(()) } - /// Add all trace columns in the specified trace segment by their identifiers and indices. + /// Add all trace columns in the specified trace segment by their identifiers, sizes and indices. pub(super) fn insert_trace_columns( &mut self, trace_segment: TraceSegment, @@ -149,8 +112,12 @@ impl SymbolTable { let mut col_idx = 0; for trace_cols in trace { - let trace_column = TraceColumn::new(trace_segment, col_idx); - self.insert_symbol(trace_cols.name(), IdentifierType::TraceColumn(trace_column))?; + let trace_columns = + TraceColumns::new(trace_segment, col_idx, trace_cols.size() as usize); + self.insert_symbol( + trace_cols.name(), + IdentifierType::TraceColumns(trace_columns), + )?; col_idx += trace_cols.size() as usize; } @@ -271,13 +238,13 @@ impl SymbolTable { )) } } - IdentifierType::TraceColumnGroup(trace_column_group) => { - if vector_access.idx() < trace_column_group.size() { + IdentifierType::TraceColumns(trace_columns) => { + if vector_access.idx() < trace_columns.size() { Ok(symbol_type) } else { Err(SemanticError::vector_access_out_of_bounds( vector_access, - trace_column_group.size(), + trace_columns.size(), )) } } diff --git a/ir/src/tests/mod.rs b/ir/src/tests/mod.rs index bd153769..c728263c 100644 --- a/ir/src/tests/mod.rs +++ b/ir/src/tests/mod.rs @@ -43,10 +43,9 @@ fn boundary_constraints_with_constants() { #[test] fn trace_cols_groups() { let source = " - constants: - A: 123 - B: [1, 2, 3] - C: [[1, 2, 3], [4, 5, 6]] + const A = 123 + const B = [1, 2, 3] + const C = [[1, 2, 3], [4, 5, 6]] trace_columns: main: [clk, a[4]] public_inputs: @@ -58,6 +57,7 @@ fn trace_cols_groups() { enf clk.last = B[0] + C[0][1]"; let parsed = parse(source).expect("Parsing failed"); + let result = AirIR::from_source(&parsed); assert!(result.is_ok()); } @@ -66,10 +66,9 @@ fn trace_cols_groups() { fn err_trace_cols_access_out_of_bounds() { // out of bounds in transition constraints let source = " - constants: - A: 123 - B: [1, 2, 3] - C: [[1, 2, 3], [4, 5, 6]] + const A = 123 + const B = [1, 2, 3] + const C = [[1, 2, 3], [4, 5, 6]] trace_columns: main: [clk, a[4]] public_inputs: @@ -87,10 +86,9 @@ fn err_trace_cols_access_out_of_bounds() { // out of bounds in boundary constraints let source = " - constants: - A: 123 - B: [1, 2, 3] - C: [[1, 2, 3], [4, 5, 6]] + const A = 123 + const B = [1, 2, 3] + const C = [[1, 2, 3], [4, 5, 6]] trace_columns: main: [clk, a[4]] public_inputs: diff --git a/ir/src/trace_column.rs b/ir/src/trace_column.rs deleted file mode 100644 index 643a8b43..00000000 --- a/ir/src/trace_column.rs +++ /dev/null @@ -1,61 +0,0 @@ -use super::TraceSegment; - -/// Describes a column in the execution trace by the trace segment to which it belongs and its -/// index within that segment. -#[derive(Debug, Copy, Clone)] -pub struct TraceColumn { - trace_segment: TraceSegment, - col_idx: usize, -} - -impl TraceColumn { - /// Creates a [TraceColumn] in the specified trace segment at the specified index. - pub fn new(trace_segment: TraceSegment, col_idx: usize) -> Self { - Self { - trace_segment, - col_idx, - } - } - - /// Gets the trace segment of this [TraceColumn]. - pub fn trace_segment(&self) -> TraceSegment { - self.trace_segment - } - - /// Gets the column index of this [TraceColumn]. - pub fn col_idx(&self) -> usize { - self.col_idx - } -} - -#[derive(Debug, Clone)] -pub struct TraceColumnGroup { - trace_segment: TraceSegment, - size: usize, - start_col_idx: usize, -} - -impl TraceColumnGroup { - /// Creates a [TraceColumnGroup] in the specified trace segment at the specified start index. - pub fn new(trace_segment: TraceSegment, size: usize, start_col_idx: usize) -> Self { - Self { - trace_segment, - size, - start_col_idx, - } - } - - /// Gets the trace segment of this [TraceColumn]. - pub fn trace_segment(&self) -> TraceSegment { - self.trace_segment - } - - pub fn size(&self) -> usize { - self.size - } - - /// Gets the start column index of this [TraceColumn]. - pub fn start_col_idx(&self) -> usize { - self.start_col_idx - } -} \ No newline at end of file diff --git a/ir/src/trace_columns.rs b/ir/src/trace_columns.rs new file mode 100644 index 00000000..780c7654 --- /dev/null +++ b/ir/src/trace_columns.rs @@ -0,0 +1,36 @@ +use super::TraceSegment; + +/// Describes columns in the execution trace by the trace segment to which it belongs, it's size +/// and it's offset. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct TraceColumns { + trace_segment: TraceSegment, + offset: usize, + size: usize, +} + +impl TraceColumns { + /// Creates a [TraceColumns] in the specified trace segment of the specified size and offset. + pub fn new(trace_segment: TraceSegment, offset: usize, size: usize) -> Self { + Self { + trace_segment, + size, + offset, + } + } + + /// Returns the trace segment of this [TraceColumns]. + pub fn trace_segment(&self) -> TraceSegment { + self.trace_segment + } + + /// Returns the offset of this [TraceColumns]. + pub fn offset(&self) -> usize { + self.offset + } + + /// Returns the size of this [TraceColumns]. + pub fn size(&self) -> usize { + self.size + } +} diff --git a/ir/src/transition_stmts/graph.rs b/ir/src/transition_stmts/graph.rs index 8a094245..7bc2b19b 100644 --- a/ir/src/transition_stmts/graph.rs +++ b/ir/src/transition_stmts/graph.rs @@ -1,11 +1,10 @@ use super::{ super::BTreeMap, degree::TransitionConstraintDegree, SemanticError, SymbolTable, TraceSegment, }; -use crate::{symbol_table::IdentifierType, VariableRoots}; +use crate::{symbol_table::IdentifierType, VariableRoots, CURRENT_ROW, NEXT_ROW}; use parser::ast::{ - constants::ConstantType, Identifier, MatrixAccess, TransitionExpr, TransitionVariableType, - VectorAccess, - self, constants::ConstantType, Identifier, MatrixAccess, TransitionExpr, VectorAccess, + self, constants::ConstantType, Identifier, MatrixAccess, TransitionExpr, + TransitionVariableType, VectorAccess, }; // ALGEBRAIC GRAPH @@ -109,9 +108,7 @@ impl AlgebraicGraph { TransitionExpr::MatrixAccess(matrix_access) => { self.insert_matrix_access(symbol_table, &matrix_access, variable_roots) } - TransitionExpr::Next(trace_access) => { - self.insert_next(symbol_table, &trace_access) - } + TransitionExpr::Next(trace_access) => self.insert_next(symbol_table, &trace_access), TransitionExpr::Rand(index) => { // constraint target for random values defaults to the second trace segment. // TODO: make this more general, so random values from further trace segments can be @@ -165,38 +162,25 @@ impl AlgebraicGraph { fn insert_next( &mut self, symbol_table: &SymbolTable, - trace_col_access: &ast::TraceAccess, + trace_access: &ast::TraceAccess, ) -> Result<(TraceSegment, NodeIndex), SemanticError> { - match trace_col_access { - TraceColAccess::Single(ident) => { - let col_type = symbol_table.get_type(ident.name())?; - if let IdentifierType::TraceColumn(column) = col_type { - let trace_segment = column.trace_segment(); - let trace_access = TraceAccess::new(trace_segment, column.col_idx(), 1); - let node_index = self.insert_op(Operation::TraceElement(trace_access)); - Ok((trace_segment, node_index)) - } else { - Err(SemanticError::InvalidUsage(format!( - "Identifier {} was declared as a {} not as a trace column", - ident, col_type - ))) - } - } - TraceColAccess::GroupAccess(ident, idx) => { - let col_type = symbol_table.get_type(ident.name())?; - if let IdentifierType::TraceColumnGroup(column_group) = col_type { - let trace_segment = column_group.trace_segment(); - let trace_access = - TraceAccess::new(trace_segment, idx + column_group.start_col_idx(), 1); - let node_index = self.insert_op(Operation::TraceElement(trace_access)); - Ok((trace_segment, node_index)) - } else { - Err(SemanticError::InvalidUsage(format!( - "Identifier {} was declared as a {} not as a trace column group", - ident, col_type - ))) - } + let col_type = symbol_table.get_type(trace_access.name())?; + match col_type { + IdentifierType::TraceColumns(columns) => { + let trace_segment = columns.trace_segment(); + let trace_access = TraceAccess::new( + trace_segment, + columns.offset() + trace_access.idx(), + NEXT_ROW, + ); + let node_index = self.insert_op(Operation::TraceElement(trace_access)); + Ok((trace_segment, node_index)) } + _ => Err(SemanticError::InvalidUsage(format!( + "Identifier {} was declared as a {} not as a trace column", + trace_access.name(), + col_type + ))), } } @@ -214,9 +198,9 @@ impl AlgebraicGraph { ) -> Result<(TraceSegment, NodeIndex), SemanticError> { let elem_type = symbol_table.get_type(ident)?; match elem_type { - IdentifierType::TraceColumn(column) => { - let trace_segment = column.trace_segment(); - let trace_access = TraceAccess::new(trace_segment, column.col_idx(), 0); + IdentifierType::TraceColumns(columns) => { + let trace_segment = columns.trace_segment(); + let trace_access = TraceAccess::new(trace_segment, columns.offset(), CURRENT_ROW); let node_index = self.insert_op(Operation::TraceElement(trace_access)); Ok((trace_segment, node_index)) } @@ -305,13 +289,13 @@ impl AlgebraicGraph { ))) } } - IdentifierType::TraceColumnGroup(trace_column_group) => { - let trace_segment = trace_column_group.trace_segment(); - let col_idx = trace_column_group.start_col_idx() + vector_access.idx(); + IdentifierType::TraceColumns(columns) => { + let trace_segment = columns.trace_segment(); + let col_idx = columns.offset() + vector_access.idx(); let node_index = self.insert_op(Operation::TraceElement(TraceAccess::new( trace_segment, col_idx, - 0, + CURRENT_ROW, ))); Ok((trace_segment, node_index)) } diff --git a/parser/src/lexer/mod.rs b/parser/src/lexer/mod.rs index cab80681..ef1e266d 100644 --- a/parser/src/lexer/mod.rs +++ b/parser/src/lexer/mod.rs @@ -37,7 +37,7 @@ pub enum Token { /// Used to declare trace columns section in the AIR constraints module. #[token("trace_columns")] - TraceColumnns, + TraceColumns, /// Used to declare main trace columns. #[token("main")] diff --git a/parser/src/parser/grammar.lalrpop b/parser/src/parser/grammar.lalrpop index f4b87f6b..98cf80ce 100644 --- a/parser/src/parser/grammar.lalrpop +++ b/parser/src/parser/grammar.lalrpop @@ -321,7 +321,7 @@ extern { "def" => Token::Def, "let" => Token::Let, "const" => Token::Const, - "trace_columns" => Token::TraceColumnns, + "trace_columns" => Token::TraceColumns, "main" => Token::Main, "aux" => Token::Aux, "public_inputs" => Token::PublicInputs,