Functions
Functions are the entry points to a virtual machine. They can be called from another machine or from the outside.
In this section, we describe functions with this simple virtual machine:
machine Machine with degree: 16 {
reg pc[@pc];
reg X[<=];
reg Y[<=];
reg Z[<=];
reg CNT;
reg A;
reg B;
// an instruction to assert that a number is zero
instr assert_zero X {
X = 0
}
// an instruction to jump to a label
instr jmp l: label {
pc' = l
}
// an instruction to jump to a label iff `X` is `0`, otherwise continue
instr jmpz X, l: label {
pc' = XIsZero * l + (1 - XIsZero) * (pc + 1)
}
// an instruction to return the square of an input as well as its double
instr square_and_double X -> Y, Z {
Y = X * X,
Z = 2 * X
}
function main {
// initialise `A` to 2
A <=X= 2;
// initialise `CNT` to `3`
CNT <=X= 3;
start:
// if `CNT` is `0`, jump to `end`
jmpz CNT, end;
// decrement `CNT`
CNT <=X= CNT - 1;
// get the square and the double of `A`
A, B <== square_and_double(A);
// jump back to `start`
jmp start;
end:
// check that `A == ((2**2)**2)**2`
assert_zero A - ((2**2)**2)**2;
// check that `B == ((2**2)**2)*2`
assert_zero B - ((2**2)**2)*2;
return;
}
// some superpowers on `X` to allow us to check if it's 0
col witness XInv;
col witness XIsZero;
XIsZero = 1 - X * XInv;
XIsZero * X = 0;
XIsZero * (1 - XIsZero) = 0;
}
Function inputs and outputs
Function inputs and outputs are not supported yet
Statements
Labels
Labels allow referring to a location in a function by name.
start:
Assignments
Assignments allow setting the values of some write registers to the values of some expressions expression using assignment registers.
CNT <=X= 3;
If the right-hand side of the assignment is an instruction, assignment registers can be inferred and are optional:
A, B <== square_and_double(A);
This will be inferred to be the same as A, B <=Y, Z= square_and_double(A);
from the definition of the instruction:
instr square_and_double X -> Y, Z {
Y = X * X,
Z = 2 * X
}
Instructions
Instructions which do not return outputs can be used as statements.
assert_zero A - ((2**2)**2)**2;