Merge pull request #1001 from powdr-labs/semicolon

require semicolon in `instr and Y, Z -> X = binary.and;` declarations
This commit is contained in:
chriseth
2024-02-06 08:22:25 +00:00
committed by GitHub
26 changed files with 265 additions and 99 deletions

View File

@@ -36,9 +36,9 @@ machine Main {
reg Y[<=];
reg A;
instr identity X -> Y = sub.identity
instr one -> Y = sub.one
instr nothing = sub.nothing
instr identity X -> Y = sub.identity;
instr one -> Y = sub.one;
instr nothing = sub.nothing;
function main {
start:
@@ -662,4 +662,4 @@ pol constant _block_enforcer_last_step = [0]* + [1];
pol commit _operation_id_no_change;
_operation_id_no_change = ((1 - _block_enforcer_last_step) * (1 - instr_return));
(_operation_id_no_change * (_operation_id' - _operation_id)) = 0;
```
```

View File

@@ -33,13 +33,28 @@ impl<T: Display> Display for ModuleStatement<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
ModuleStatement::SymbolDefinition(SymbolDefinition { name, value }) => match value {
SymbolValue::Machine(m) => {
write!(f, "machine {name} {m}")
}
SymbolValue::Machine(
m @ Machine {
arguments:
MachineArguments {
latch,
operation_id,
},
..
},
) => match (latch, operation_id) {
(None, None) => write!(f, "machine {name} {m}"),
(Some(latch), None) => write!(f, "machine {name}({latch}, _) {m}"),
(None, Some(op_id)) => write!(f, "machine {name}(_, {op_id}) {m}"),
(Some(latch), Some(op_id)) => write!(f, "machine {name}({latch}, {op_id}) {m}"),
},
SymbolValue::Import(i) => {
write!(f, "{i} as {name}")
write!(f, "{i} as {name};")
}
SymbolValue::Module(m) => {
SymbolValue::Module(m @ Module::External(_)) => {
write!(f, "mod {m}")
}
SymbolValue::Module(m @ Module::Local(_)) => {
write!(f, "mod {name} {m}")
}
SymbolValue::Expression(e) => {
@@ -80,12 +95,34 @@ impl<T: Display> Display for Machine<T> {
impl<T: Display> Display for InstructionBody<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
InstructionBody::Local(elements) => write!(f, "{{ {} }}", elements.iter().format(", ")),
InstructionBody::Local(elements) => write!(
f,
"{{ {} }}",
elements
.iter()
.map(format_instruction_statement)
.format(", ")
),
InstructionBody::CallableRef(r) => write!(f, " = {r};"),
}
}
}
fn format_instruction_statement<T: Display>(stmt: &PilStatement<T>) -> String {
match stmt {
PilStatement::PolynomialIdentity(_, _)
| PilStatement::PlookupIdentity(_, _, _)
| PilStatement::PermutationIdentity(_, _, _)
| PilStatement::ConnectIdentity(_, _, _) => {
// statements inside instruction definition don't end in semicolon
let mut s = format!("{stmt}");
assert_eq!(s.pop(), Some(';'));
s
}
_ => panic!("invalid statement inside instruction body: {}", stmt),
}
}
impl<T: Display> Display for Instruction<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(
@@ -119,7 +156,7 @@ impl<T: Display> Display for MachineStatement<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
MachineStatement::Degree(_, degree) => write!(f, "degree {};", degree),
MachineStatement::Pil(_, statement) => write!(f, "{statement};"),
MachineStatement::Pil(_, statement) => write!(f, "{statement}"),
MachineStatement::Submachine(_, ty, name) => write!(f, "{ty} {name};"),
MachineStatement::RegisterDeclaration(_, name, flag) => write!(
f,

View File

@@ -446,7 +446,7 @@ namespace main_sub(16);
pol constant p_line = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + [10]*;
pol commit X_free_value(i) query match pc(i) { 2 => ("input", 1), 4 => ("input", (std::convert::int(CNT(i)) + 1)), 7 => ("input", 0), };
pol constant p_X_const = [0]*;
pol constant p_X_read_free = [0, 0, 1, 0, 1, 0, 0, -1, 0, 0, 0] + [0]*;
pol constant p_X_read_free = [0, 0, 1, 0, 1, 0, 0, 18446744069414584320, 0, 0, 0] + [0]*;
pol constant p_instr__jump_to_operation = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] + [0]*;
pol constant p_instr__loop = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] + [1]*;
pol constant p_instr__reset = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + [0]*;
@@ -519,7 +519,7 @@ machine Machine {
pol constant p_instr__loop = [0, 0, 0, 0, 1] + [1]*;
pol constant p_instr__reset = [1, 0, 0, 0, 0] + [0]*;
pol constant p_instr_adjust_fp = [0, 0, 0, 1, 0] + [0]*;
pol constant p_instr_adjust_fp_param_amount = [0, 0, 0, -2, 0] + [0]*;
pol constant p_instr_adjust_fp_param_amount = [0, 0, 0, 18446744069414584319, 0] + [0]*;
pol constant p_instr_adjust_fp_param_t = [0, 0, 0, 3, 0] + [0]*;
pol constant p_instr_inc_fp = [0, 0, 1, 0, 0] + [0]*;
pol constant p_instr_inc_fp_param_amount = [0, 0, 7, 0, 0] + [0]*;

View File

@@ -433,13 +433,7 @@ macro_rules! powdr_field {
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = self.to_integer().value;
if self.is_in_lower_half() {
write!(f, "{value}")
} else {
let mut res = Self::modulus();
assert!(!res.value.sub_with_borrow(&value));
write!(f, "-{}", res)
}
write!(f, "{value}")
}
}
};

View File

@@ -24,6 +24,8 @@ regex-syntax = { version = "0.6", default_features = false, features = ["unicode
pretty_assertions = "1.3.0"
test-log = "0.2.12"
env_logger = "0.10.0"
walkdir = "2.4.0"
similar = "2.4"
[build-dependencies]
lalrpop = "^0.19"

View File

@@ -94,12 +94,15 @@ pub fn unescape_string(s: &str) -> String {
mod test {
use super::*;
use powdr_ast::parsed::{
build::direct_reference, PILFile, PilStatement, PolynomialName, SelectedExpressions,
asm::ASMProgram, build::direct_reference, PILFile, PilStatement, PolynomialName,
SelectedExpressions,
};
use powdr_number::Bn254Field;
use powdr_number::GoldilocksField;
use powdr_parser_util::UnwrapErrToStderr;
use std::fs;
use similar::TextDiff;
use test_log::test;
use walkdir::WalkDir;
#[test]
fn empty() {
@@ -191,49 +194,181 @@ mod test {
);
}
fn parse_file(name: &str) -> PILFile<GoldilocksField> {
let file = std::path::PathBuf::from(format!(
"{}/../test_data/{name}",
env!("CARGO_MANIFEST_DIR")
));
let input = fs::read_to_string(file).unwrap();
parse(Some(name), &input).unwrap_err_to_stderr()
fn find_files_with_ext(
dir: std::path::PathBuf,
ext: String,
) -> impl Iterator<Item = (String, String)> {
WalkDir::new(&dir).into_iter().filter_map(move |e| {
let entry = e.unwrap();
let path = entry.path();
match path.extension() {
Some(path_ext) if path_ext.to_str() == Some(&ext) => Some((
std::fs::canonicalize(path)
.unwrap()
.to_str()
.unwrap()
.into(),
std::fs::read_to_string(path).unwrap(),
)),
_ => None,
}
})
}
fn parse_asm_file(name: &str) -> ASMProgram<GoldilocksField> {
let file = std::path::PathBuf::from(format!(
"{}/../test_data/{name}",
env!("CARGO_MANIFEST_DIR")
));
// helper function to clear SourceRef's inside the AST so we can compare for equality
fn pil_clear_source_refs<T>(ast: &mut PILFile<T>) {
ast.0.iter_mut().for_each(pil_statement_clear_source_ref);
}
let input = fs::read_to_string(file).unwrap();
parse_asm(Some(name), &input).unwrap_err_to_stderr()
fn pil_statement_clear_source_ref<T>(stmt: &mut PilStatement<T>) {
match stmt {
PilStatement::Include(s, _)
| PilStatement::Namespace(s, _, _)
| PilStatement::LetStatement(s, _, _)
| PilStatement::PolynomialDefinition(s, _, _)
| PilStatement::PublicDeclaration(s, _, _, _, _)
| PilStatement::PolynomialConstantDeclaration(s, _)
| PilStatement::PolynomialConstantDefinition(s, _, _)
| PilStatement::PolynomialCommitDeclaration(s, _, _)
| PilStatement::PolynomialIdentity(s, _)
| PilStatement::PlookupIdentity(s, _, _)
| PilStatement::PermutationIdentity(s, _, _)
| PilStatement::ConnectIdentity(s, _, _)
| PilStatement::ConstantDefinition(s, _, _)
| PilStatement::Expression(s, _) => *s = SourceRef::unknown(),
}
}
// helper function to clear SourceRef's inside the AST so we can compare for equality
fn asm_clear_source_refs<T>(ast: &mut ASMProgram<T>) {
use powdr_ast::parsed::asm::{
ASMModule, FunctionStatement, Instruction, InstructionBody, LinkDeclaration, Machine,
MachineStatement, Module, ModuleStatement, SymbolDefinition, SymbolValue,
};
fn clear_machine_stmt<T>(stmt: &mut MachineStatement<T>) {
match stmt {
MachineStatement::Degree(s, _)
| MachineStatement::Submachine(s, _, _)
| MachineStatement::RegisterDeclaration(s, _, _)
| MachineStatement::OperationDeclaration(s, _, _, _)
| MachineStatement::LinkDeclaration(LinkDeclaration { source: s, .. }) => {
*s = SourceRef::unknown();
}
MachineStatement::Pil(s, stmt) => {
*s = SourceRef::unknown();
pil_statement_clear_source_ref(stmt)
}
MachineStatement::InstructionDeclaration(s, _, Instruction { body, .. }) => {
*s = SourceRef::unknown();
if let InstructionBody::Local(statements) = body {
statements
.iter_mut()
.for_each(pil_statement_clear_source_ref)
}
}
MachineStatement::FunctionDeclaration(s, _, _, statements) => {
*s = SourceRef::unknown();
for fstmt in statements {
match fstmt {
FunctionStatement::Assignment(s, _, _, _)
| FunctionStatement::Instruction(s, _, _)
| FunctionStatement::Label(s, _)
| FunctionStatement::DebugDirective(s, _)
| FunctionStatement::Return(s, _) => *s = SourceRef::unknown(),
}
}
}
}
}
fn clear_module_stmt<T>(stmt: &mut ModuleStatement<T>) {
let ModuleStatement::SymbolDefinition(SymbolDefinition { value, .. }) = stmt;
match value {
SymbolValue::Machine(Machine { statements, .. }) => {
statements.iter_mut().for_each(clear_machine_stmt)
}
SymbolValue::Module(Module::Local(ASMModule { statements })) => {
statements.iter_mut().for_each(clear_module_stmt);
}
SymbolValue::Module(Module::External(_))
| SymbolValue::Import(_)
| SymbolValue::Expression(_) => (),
}
}
ast.main.statements.iter_mut().for_each(clear_module_stmt);
}
#[test]
fn parse_example_files() {
parse_file("polygon-hermez/arith.pil");
parse_file("polygon-hermez/binary.pil");
parse_file("polygon-hermez/byte4.pil");
parse_file("polygon-hermez/config.pil");
parse_file("polygon-hermez/global.pil");
parse_file("polygon-hermez/keccakf.pil");
parse_file("polygon-hermez/main.pil");
parse_file("polygon-hermez/mem_align.pil");
parse_file("polygon-hermez/mem.pil");
parse_file("polygon-hermez/nine2one.pil");
parse_file("polygon-hermez/padding_kk.pil");
parse_file("polygon-hermez/padding_kkbit.pil");
parse_file("polygon-hermez/padding_pg.pil");
parse_file("polygon-hermez/poseidong.pil");
parse_file("polygon-hermez/rom.pil");
parse_file("polygon-hermez/storage.pil");
/// Test that (source -> AST -> source -> AST) works properly for asm files
fn parse_write_reparse_asm() {
let crate_dir = env!("CARGO_MANIFEST_DIR");
let basedir = std::path::PathBuf::from(format!("{crate_dir}/../test_data/"));
let asm_files = find_files_with_ext(basedir, "asm".into());
for (file, orig_string) in asm_files {
let mut orig_asm =
parse_asm::<Bn254Field>(Some(&file), &orig_string).unwrap_err_to_stderr();
let orig_asm_to_string = format!("{}", orig_asm);
let mut reparsed_asm = parse_asm::<Bn254Field>(
Some((file.clone() + " reparsed").as_ref()),
&orig_asm_to_string,
)
.unwrap_err_to_stderr();
asm_clear_source_refs(&mut orig_asm);
asm_clear_source_refs(&mut reparsed_asm);
if orig_asm != reparsed_asm {
let orig_ast = format!("{orig_asm:#?}");
let reparsed_ast = format!("{reparsed_asm:#?}");
let diff = TextDiff::from_lines(&orig_ast, &reparsed_ast);
eprintln!("parsed and re-parsed ASTs differ:");
for change in diff.iter_all_changes() {
let sign = match change.tag() {
similar::ChangeTag::Delete => "-",
similar::ChangeTag::Insert => "+",
similar::ChangeTag::Equal => " ",
};
eprint!("\t{}{}", sign, change);
}
panic!("parsed and re-parsed ASTs differ for file: {file}");
}
}
}
#[test]
fn parse_example_asm_files() {
parse_asm_file("asm/simple_sum.asm");
/// Test that (source -> AST -> source -> AST) works properly for pil files
fn parse_write_reparse_pil() {
let crate_dir = env!("CARGO_MANIFEST_DIR");
let basedir = std::path::PathBuf::from(format!("{crate_dir}/../test_data/"));
let pil_files = find_files_with_ext(basedir, "pil".into());
for (file, orig_string) in pil_files {
let mut orig_pil =
parse::<Bn254Field>(Some(&file), &orig_string).unwrap_err_to_stderr();
let orig_pil_to_string = format!("{}", orig_pil);
let mut reparsed_pil = parse::<Bn254Field>(
Some((file.clone() + " reparsed").as_ref()),
&orig_pil_to_string,
)
.unwrap_err_to_stderr();
pil_clear_source_refs(&mut orig_pil);
pil_clear_source_refs(&mut reparsed_pil);
assert_eq!(orig_pil, reparsed_pil);
if orig_pil != reparsed_pil {
let orig_ast = format!("{orig_pil:#?}");
let reparsed_ast = format!("{reparsed_pil:#?}");
let diff = TextDiff::from_lines(&orig_ast, &reparsed_ast);
eprintln!("parsed and re-parsed ASTs differ:");
for change in diff.iter_all_changes() {
let sign = match change.tag() {
similar::ChangeTag::Delete => "-",
similar::ChangeTag::Insert => "+",
similar::ChangeTag::Equal => " ",
};
eprint!("\t{}{}", sign, change);
}
panic!("parsed and re-parsed ASTs differ for file: {file}");
}
}
}
mod display {

View File

@@ -254,7 +254,7 @@ pub LinkDeclaration: MachineStatement<T> = {
pub InstructionBody: InstructionBody<T> = {
"{}" => InstructionBody::Local(vec![]),
"{" <InstructionBodyElements> "}" => InstructionBody::Local(<>),
"=" <f_ref:CallableRef> => InstructionBody::CallableRef(f_ref),
"=" <f_ref:CallableRef> ";" => InstructionBody::CallableRef(f_ref),
}
pub CallableRef: CallableRef = {
@@ -565,8 +565,6 @@ SpecialIdentifier: &'input str = {
}
ConstantIdentifier: String = {
// TODO it seems the lexer splits the token after %
"%N" => <>.to_string(),
r"%[a-zA-Z_][a-zA-Z$_0-9@]*" => <>.to_string(),
}

View File

@@ -63,7 +63,7 @@ fn test_external_witgen_both_provided() {
}
#[test]
#[should_panic = "called `Result::unwrap()` on an `Err` value: Generic(\"main.b = (main.a + 1);:\\n Linear constraint is not satisfiable: -1 != 0\")"]
#[should_panic = "called `Result::unwrap()` on an `Err` value: Generic(\"main.b = (main.a + 1);:\\n Linear constraint is not satisfiable: 18446744069414584320 != 0\")"]
fn test_external_witgen_fails_on_conflicting_external_witness() {
let f = "pil/external_witgen.pil";
let external_witness = vec![

View File

@@ -20,9 +20,9 @@ static BINARY_COPROCESSOR: CoProcessor = CoProcessor {
import: "use std::binary::Binary;",
instructions: r#"
// ================= binary/bitwise instructions =================
instr and Y, Z -> X = binary.and
instr or Y, Z -> X = binary.or
instr xor Y, Z -> X = binary.xor
instr and Y, Z -> X = binary.and;
instr or Y, Z -> X = binary.or;
instr xor Y, Z -> X = binary.xor;
"#,
runtime_function_impl: None,
@@ -34,8 +34,8 @@ static SHIFT_COPROCESSOR: CoProcessor = CoProcessor {
import: "use std::shift::Shift;",
instructions: r#"
// ================= shift instructions =================
instr shl Y, Z -> X = shift.shl
instr shr Y, Z -> X = shift.shr
instr shl Y, Z -> X = shift.shl;
instr shr Y, Z -> X = shift.shr;
"#,
runtime_function_impl: None,
@@ -47,7 +47,7 @@ static SPLIT_GL_COPROCESSOR: CoProcessor = CoProcessor {
import: "use std::split::split_gl::SplitGL;",
instructions: r#"
// ================== wrapping instructions ==============
instr split_gl Z -> X, Y = split_gl.split
instr split_gl Z -> X, Y = split_gl.split;
"#,
runtime_function_impl: None,
@@ -59,7 +59,7 @@ static POSEIDON_GL_COPROCESSOR: CoProcessor = CoProcessor {
import: "use std::hash::poseidon_gl::PoseidonGL;",
instructions: r#"
// ================== hashing instructions ==============
instr poseidon_gl A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11 -> X, Y, Z, W = poseidon_gl.poseidon_permutation
instr poseidon_gl A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11 -> X, Y, Z, W = poseidon_gl.poseidon_permutation;
"#,
runtime_function_impl: Some(("poseidon_gl_coprocessor", poseidon_gl_call)),

View File

@@ -38,8 +38,8 @@ machine Main {
reg Y[<=];
reg A;
instr double X -> Y = arith.double
instr square X -> Y = arith.square
instr double X -> Y = arith.double;
instr square X -> Y = arith.square;
instr assert_eq X, Y { X = Y }
function main {

View File

@@ -35,9 +35,9 @@ machine Main {
reg pc[@pc];
instr nothing = a.nothing
instr also_nothing = b.nothing
instr still_nothing = c.nothing
instr nothing = a.nothing;
instr also_nothing = b.nothing;
instr still_nothing = c.nothing;
function main {
nothing;

View File

@@ -9,9 +9,9 @@ machine Main {
reg Y[<=];
reg A;
instr identity X -> Y = sub.identity
instr one -> Y = sub.one
instr nothing = sub.nothing
instr identity X -> Y = sub.identity;
instr one -> Y = sub.one;
instr nothing = sub.nothing;
function main {
start:

View File

@@ -41,7 +41,7 @@ machine Main {
instr assert_zero X { XIsZero = 1 }
instr sqrt X -> Y = sqrt.sqrt
instr sqrt X -> Y = sqrt.sqrt;
function main {

View File

@@ -10,8 +10,8 @@ machine Main {
reg Z[<=];
reg A;
instr add X, Y -> Z = arith.add
instr mul X, Y -> Z = arith.mul
instr add X, Y -> Z = arith.add;
instr mul X, Y -> Z = arith.mul;
instr assert_eq X, Y { X = Y }
function main {

View File

@@ -28,8 +28,8 @@ machine Main {
reg Z[<=];
reg A;
instr add X, Y -> Z = arith.add
instr sub X, Y -> Z = arith.sub
instr add X, Y -> Z = arith.add;
instr sub X, Y -> Z = arith.sub;
instr assert_eq X, Y { X = Y }
function main {

View File

@@ -40,7 +40,7 @@ machine Main {
reg X[<=];
reg A;
instr assert1 X -> = assert1.assert1
instr assert1 X -> = assert1.assert1;
instr loop {
pc' = pc

View File

@@ -43,10 +43,10 @@ machine Main {
reg Z[<=];
reg A;
instr add X, Y -> Z = arith.add
instr sub X, Y -> Z = arith.sub
instr and X, Y -> Z = binary.and
instr or X, Y -> Z = binary.or
instr add X, Y -> Z = arith.add;
instr sub X, Y -> Z = arith.sub;
instr and X, Y -> Z = binary.and;
instr or X, Y -> Z = binary.or;
instr assert_eq X, Y { X = Y }
function main {

View File

@@ -10,8 +10,8 @@ machine Main {
reg Z[<=];
reg A;
instr add X, Y -> Z = vm.add
instr sub X, Y -> Z = vm.sub
instr add X, Y -> Z = vm.add;
instr sub X, Y -> Z = vm.sub;
instr assert_eq X, Y { X = Y }
function main {

View File

@@ -10,7 +10,7 @@ machine Main {
reg Z[<=];
reg A;
instr pow X, Y -> Z = pow.pow
instr pow X, Y -> Z = pow.pow;
instr assert_eq X, Y { X = Y }
function main {

View File

@@ -10,7 +10,7 @@ machine Main {
reg Z[<=];
reg A;
instr pythagoras X, Y -> Z = pythagoras.pythagoras
instr pythagoras X, Y -> Z = pythagoras.pythagoras;
instr assert_eq X, Y { X = Y }
function main {
@@ -40,8 +40,8 @@ machine Pythagoras {
reg B;
instr add X, Y -> Z = arith.add
instr mul X, Y -> Z = arith.mul
instr add X, Y -> Z = arith.add;
instr mul X, Y -> Z = arith.mul;
function pythagoras a: field, b: field -> field {
A <== mul(a, a);

View File

@@ -10,7 +10,7 @@ machine Main {
reg Z[<=];
reg A;
instr pythagoras X, Y -> Z = pythagoras.pythagoras
instr pythagoras X, Y -> Z = pythagoras.pythagoras;
instr assert_eq X, Y { X = Y }
function main {
@@ -39,8 +39,8 @@ machine Pythagoras {
reg B;
instr add X, Y -> Z = arith.add
instr mul X, Y -> Z = arith.mul
instr add X, Y -> Z = arith.add;
instr mul X, Y -> Z = arith.mul;
function pythagoras a: field, b: field -> field {
A <== mul(a, a);

View File

@@ -64,7 +64,7 @@ machine Main{
Arith arith;
instr eq0 A0, A1, A2, A3, A4, A5, A6, A7, B0, B1, B2, B3, B4, B5, B6, B7, C0, C1, C2, C3, C4, C5, C6, C7 -> D0, D1, D2, D3, D4, D5, D6, D7, E0, E1, E2, E3, E4, E5, E6, E7 = arith.eq0
instr eq0 A0, A1, A2, A3, A4, A5, A6, A7, B0, B1, B2, B3, B4, B5, B6, B7, C0, C1, C2, C3, C4, C5, C6, C7 -> D0, D1, D2, D3, D4, D5, D6, D7, E0, E1, E2, E3, E4, E5, E6, E7 = arith.eq0;
instr assert_eq A0, A1, A2, A3, A4, A5, A6, A7, B0, B1, B2, B3, B4, B5, B6, B7 {
A0 = B0,

View File

@@ -12,7 +12,7 @@ machine Main {
PoseidonBN254 poseidon;
instr poseidon X0, X1, X2 -> X3 = poseidon.poseidon_permutation
instr poseidon X0, X1, X2 -> X3 = poseidon.poseidon_permutation;
instr assert_eq X0, X1 {
X0 = X1

View File

@@ -27,7 +27,7 @@ machine Main {
PoseidonGL poseidon;
instr poseidon X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11 -> X12, X13, X14, X15 = poseidon.poseidon_permutation
instr poseidon X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11 -> X12, X13, X14, X15 = poseidon.poseidon_permutation;
instr assert_eq X0, X1 {
X0 = X1

View File

@@ -25,7 +25,7 @@ machine Main {
SplitBN254 split_machine;
instr split X0 -> X1, X2, X3, X4, X5, X6, X7, X8 = split_machine.split
instr split X0 -> X1, X2, X3, X4, X5, X6, X7, X8 = split_machine.split;
instr assert_eq X0, X1 {
X0 = X1

View File

@@ -13,7 +13,7 @@ machine Main {
SplitGL split_machine;
instr split X0 -> X1, X2 = split_machine.split
instr split X0 -> X1, X2 = split_machine.split;
instr assert_eq X0, X1 {
X0 = X1