type variable = string type p_exp = Main of variable * variable * c_exp (* def main with input x output y as c *) and c_exp = Skip | Assignment of variable * a_exp (* x := a *) | Sequence of c_exp * c_exp (* c; c *) | If of b_exp * c_exp * c_exp (* if b then c else c *) | While of b_exp * c_exp (* while b do c *) | For of c_exp * b_exp * c_exp * c_exp (* for c; b; c do c *) and b_exp = Boolean of bool (* v *) | BAnd of b_exp * b_exp (* b and b *) | BOr of b_exp * b_exp (* b or b *) | BNot of b_exp (* not b *) | BCmp of a_exp * a_exp (* a = a *) | BCmpLess of a_exp * a_exp (* a < a *) | BCmpLessEq of a_exp * a_exp (* a <= a *) | BCmpGreater of a_exp * a_exp (* a > a *) | BCmpGreaterEq of a_exp * a_exp (* a >= a *) and a_exp = Variable of variable (* x *) | Integer of int (* n *) | Plus of a_exp * a_exp (* a + a *) | Minus of a_exp * a_exp (* a - a *) | Times of a_exp * a_exp (* a * a *) | Division of a_exp * a_exp (* a / a *) | Modulo of a_exp * a_exp (* a % a *) | Power of a_exp * a_exp (* a ^ a *) | PowerMod of a_exp * a_exp * a_exp (* a ^ a % a *) | Rand of a_exp (* rand(0, a) *) module VariableMap : Map.S with type key = variable type memory = { assignments: int VariableMap.t } exception AbsentAssignment of string val reduce : p_exp -> int -> int