diff --git a/bin/main.ml b/bin/main.ml index 69799b9..c6a0569 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -1,222 +1 @@ -open Lang.MiniImp - -(* -------------------------------------------------------------------------- *) -(* Identity program *) -let program = - Main - ("a", - "b", - (Assignment ("b", (Variable "a"))) - ) -;; - -Printf.printf "%d\n" (reduce 1 program) - -(* -------------------------------------------------------------------------- *) -(* y not defined program *) -let program = - Main - ("a", - "b", - (Sequence ( - (Assignment ("x", (Integer 1))), - (Assignment ("b", - (Plus ((Plus (Variable "a", Variable "x")), (Variable "y"))))) - ) - ) - ) -;; - -try - Printf.printf "%d\n" (reduce 100 program) -with AbsentAssignment s -> - Printf.printf "%s\n" s -;; - -(* -------------------------------------------------------------------------- *) -(* factorial program *) -let program = - Main - ("a", - "b", - (Sequence ( - (Assignment ("b", (Integer 1))), - (For ( - (Assignment ("i", (Integer 1))), - (BCmpLessEq (Variable "i", Variable "a")), - (Assignment ("i", (Plus ((Variable "i"), (Integer 1))))), - (Assignment ("b", (Times (Variable "b", Variable "i")))) - ) - ) - ) - ) - ) -;; - -Printf.printf "%d\n" (reduce 10 program) -;; - -(* -------------------------------------------------------------------------- *) -(* hailstone sequence's lenght program *) -let program = - Main - ("a", - "b", - (Sequence ( - (Assignment ("b", (Integer 1))), - (While ( - (BNot (BCmp ((Variable "a"), (Integer 1)))), - (Sequence ( - (Assignment ("b", (Plus (Variable "b", Integer 1)))), - (If ( - (BCmp (Modulo (Variable "a", Integer 2), Integer 1)), - (Assignment ("a", Plus (Times (Integer 3, Variable "a"), Integer 1))), - (Assignment ("a", Division (Variable "a", Integer 2))) - )) - )) - )) - )) - ) -;; - -Printf.printf "%d\n" (reduce 77031 program) -;; - -(* -------------------------------------------------------------------------- *) -(* sum multiples of 3 and 5 program *) -let program = - Main - ("a", - "b", - (Sequence ( - (Assignment ("b", (Integer 0))), - (For ( - (Assignment ("i", Integer 0)), - (BCmpLess (Variable "i", Variable "a")), - (Assignment ("i", Plus (Variable "i", Integer 1))), - (If ( - (BOr ((BCmp (Modulo (Variable "i", Integer 3), Integer 0)), - (BCmp (Modulo (Variable "i", Integer 5), Integer 0)))), - (Assignment ("b", Plus (Variable "b", Variable "i"))), - (Skip) - )) - )) - )) - ) -;; - -Printf.printf "%d\n" (reduce 12345 program) -;; - -(* -------------------------------------------------------------------------- *) -(* rand program *) -let program = - Main - ("a", - "b", - (Assignment ("b", Rand (Variable "a"))) - ) -;; - -Printf.printf "%d\n" (reduce 10 program) -;; - -(* -------------------------------------------------------------------------- *) -(* fibonacci program *) -let program = - Main - ("n", - "fnext", - (Sequence ( - Sequence ( - (Assignment ("fnow", Integer 0)), - (Assignment ("fnext", Integer 1)) - ), - (While ( - (BCmpGreater (Variable "n", Integer 1)), - (Sequence ( - (Sequence ( - (Assignment ("tmp", Plus (Variable "fnow", Variable "fnext"))), - (Assignment ("fnow", Variable "fnext")) - )), - (Sequence ( - (Assignment ("fnext", Variable "tmp")), - (Assignment ("n", Minus (Variable "n", Integer 1))) - )) - )))) - )) - ) -;; - -Printf.printf "%d\n" (reduce 48 program) -;; - -(* -------------------------------------------------------------------------- *) -(* Miller-Rabin primality test program *) -let program = - Main - ("n", - "result", - Sequence ( - (Assignment ("result", Integer 0)), - (Sequence ( - (Sequence ( - (Assignment ("s", Integer 0)), - (While ( - (BCmp (Integer 0, - Modulo ( - Division ( - (Minus (Variable "n", Integer 1)), - (Power (Integer 2, Variable "s"))), - (Integer 2) - ) - ) - ), - (Assignment ("s", Plus (Variable "s", Integer 1))) - )) - )), - (Sequence ( - (Assignment ("d", Division (Minus (Variable "n", Integer 1), Power (Integer 2, Variable "s")))), - (For ( - (Assignment ("i", Integer 20)), - (BCmpGreater (Variable "i", Integer 0)), - (Assignment ("i", Minus (Variable "i", Integer 1))), - (Sequence ( - Sequence ( - (Assignment ("a", Plus (Rand (Minus (Variable "n", Integer 4)), Integer 2))), - (Assignment ("x", PowerMod (Variable "a", Variable "d", Variable "n")))), - Sequence ( - (For ( - (Assignment ("j", Integer 0)), - (BCmpLess (Variable "j", Variable "s")), - (Assignment ("j", Plus (Variable "j", Integer 1))), - (Sequence ( - Sequence ( - (Assignment ("y", PowerMod (Variable "x", Integer 2, Variable "n"))), - (If ( - (BAnd (BAnd (BCmp (Variable "y", Integer 1), BNot (BCmp (Variable "x", Integer 1))), BNot (BCmp (Variable "x", Minus (Variable "n", Integer 1))))), - (Assignment ("result", Integer 1)), - (Skip) - ))), - (Assignment ("x", Variable "y")) - )) - )), - (If ( - (BNot (BCmp (Variable "y", Integer 1))), - (Assignment ("result", Integer 1)), - (Skip) - ))) - )) - )) - )) - )) - ) - ) -;; - -(* should return 0 because prime *) -Printf.printf "%d\n" (reduce 179424673 program) -;; -(* sould return 1 because not prime *) -Printf.printf "%d\n" (reduce 179424675 program) -;; +print_endline "Hello!" diff --git a/lib/miniFun.ml b/lib/miniFun.ml new file mode 100644 index 0000000..35d2b98 --- /dev/null +++ b/lib/miniFun.ml @@ -0,0 +1,358 @@ +type variable = string + +module VariableMap = Map.Make(String) + +type t_exp = + Integer of int + | Boolean of bool + | Variable of variable + | Function of variable list * t_exp + | Application of t_exp * t_exp list + | Plus of t_exp * t_exp + | Minus of t_exp * t_exp + | Times of t_exp * t_exp + | Division of t_exp * t_exp + | Modulo of t_exp * t_exp + | Power of t_exp * t_exp + | PowerMod of t_exp * t_exp * t_exp + | Rand of t_exp + | BAnd of t_exp * t_exp + | BOr of t_exp * t_exp + | BNot of t_exp + | Cmp of t_exp * t_exp + | CmpLess of t_exp * t_exp + | CmpLessEq of t_exp * t_exp + | CmpGreater of t_exp * t_exp + | CmpGreaterEq of t_exp * t_exp + | IfThenElse of t_exp * t_exp * t_exp + | LetIn of variable * t_exp * t_exp + | LetFun of variable * variable list * t_exp * t_exp + +type permittedValues = + IntegerPermitted of int + | BooleanPermitted of bool + | FunctionPermitted of closure +and closure = { + inputList: variable list; + body: t_exp; + assignments: permittedValues VariableMap.t; + recursiveness: variable option +} + +type memory = { + assignments: permittedValues VariableMap.t +} + +exception AbsentAssignment of string +exception WrongType of string +exception DivisionByZero of string +exception WrongAriety of string + +module Utility = Utility;; + +Random.self_init () + +let rec evaluate (mem: memory) (command: t_exp) = + match command with + Integer n -> (IntegerPermitted n) + | Boolean b -> (BooleanPermitted b) + | Variable v -> ( + match VariableMap.find_opt v mem.assignments with + None -> raise (AbsentAssignment ("The variable " ^ + v ^ + " is not defined.")) + | Some a -> a + ) + | Function (xs, f) -> + (FunctionPermitted + {inputList = xs; + body = f; + assignments = mem.assignments; + recursiveness = None} + ) + | Application (f, xs) -> ( + let funcClosure = ( + match (evaluate mem f) with + FunctionPermitted ff -> ff + | IntegerPermitted _ -> raise (WrongType ("Function is not a function, it's an integer")) + | BooleanPermitted _ -> raise (WrongType ("Function is not a function, it's a boolean")) + ) in + let parmList = List.map (fun k -> evaluate mem k) xs in + let rec helper m params values = + match (params, values) with + (_, []) -> (m, params) + | ([], _) -> + raise (WrongAriety ("Function application has arity " ^ + (List.length funcClosure.inputList + |> string_of_int) ^ + ", but was applied to " ^ + (List.length xs |> string_of_int) ^ + " parameters")) + | (p::tlparams, v::tlvalues) -> helper + (VariableMap.add p v m) + tlparams + tlvalues + in + let (mem2assignments, params) = helper + funcClosure.assignments + funcClosure.inputList + parmList + in (* helper funcClosure or helper mem ??? *) + let mem2 = ( + match funcClosure.recursiveness with + None -> {assignments = mem2assignments} + | Some nameF -> { + assignments = + VariableMap.add + nameF + (FunctionPermitted funcClosure) + mem2assignments + } + ) in + match params with + [] -> evaluate mem2 funcClosure.body + | _ -> ( + FunctionPermitted {funcClosure with inputList = params; + assignments = mem2assignments}) + ) + | Plus (a, b) -> + let aval = ( + match evaluate mem a with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + let bval = ( + match evaluate mem b with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + (IntegerPermitted (aval + bval)) + | Minus (a, b) -> + let aval = ( + match evaluate mem a with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + let bval = ( + match evaluate mem b with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + (IntegerPermitted (aval - bval)) + | Times (a, b) -> + let aval = ( + match evaluate mem a with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + let bval = ( + match evaluate mem b with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + (IntegerPermitted (aval * bval)) + | Division (a, b) -> + let aval = ( + match evaluate mem a with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + let bval = ( + match evaluate mem b with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in ( + try + (IntegerPermitted (aval / bval)) + with Division_by_zero -> raise (DivisionByZero "Dividing by zero") + ) + | Modulo (a, b) -> + let aval = ( + match evaluate mem a with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + let bval = ( + match evaluate mem b with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + (IntegerPermitted (aval mod bval)) + | Power (a, b) -> + let aval = ( + match evaluate mem a with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + let bval = ( + match evaluate mem b with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + (IntegerPermitted (Utility.pow aval bval)) + | PowerMod (a, b, c) -> + let aval = ( + match evaluate mem a with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + let bval = ( + match evaluate mem b with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + let cval = ( + match evaluate mem c with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + (IntegerPermitted (Utility.powmod aval bval cval)) + | Rand (a) -> + let aval = ( + match evaluate mem a with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + ) + in + IntegerPermitted (Random.int aval) + | BAnd (a, b) -> + let aval = ( + match evaluate mem a with + BooleanPermitted x -> x + | _ -> raise (WrongType ("Value is not an boolean")) + ) + in + let bval = ( + match evaluate mem b with + BooleanPermitted x -> x + | _ -> raise (WrongType ("Value is not an boolean")) + ) + in + (BooleanPermitted (aval && bval)) + | BOr (a, b) -> + let aval = ( + match evaluate mem a with + BooleanPermitted x -> x + | _ -> raise (WrongType ("Value is not an boolean")) + ) + in + let bval = ( + match evaluate mem b with + BooleanPermitted x -> x + | _ -> raise (WrongType ("Value is not an boolean")) + ) + in + (BooleanPermitted (aval || bval)) + | BNot a -> + let aval = ( + match evaluate mem a with + BooleanPermitted x -> x + | _ -> raise (WrongType ("Value is not an boolean")) + ) + in + (BooleanPermitted (not aval)) + | Cmp (exp_1, exp_2) -> ( + let exp_1val = match evaluate mem exp_1 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + let exp_2val = match evaluate mem exp_2 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + BooleanPermitted (exp_1val = exp_2val) + ) + | CmpLess (exp_1, exp_2) -> ( + let exp_1val = match evaluate mem exp_1 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + let exp_2val = match evaluate mem exp_2 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + BooleanPermitted (exp_1val < exp_2val) + ) + | CmpLessEq (exp_1, exp_2) -> ( + let exp_1val = match evaluate mem exp_1 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + let exp_2val = match evaluate mem exp_2 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + BooleanPermitted (exp_1val <= exp_2val) + ) + | CmpGreater (exp_1, exp_2) -> ( + let exp_1val = match evaluate mem exp_1 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + let exp_2val = match evaluate mem exp_2 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + BooleanPermitted (exp_1val > exp_2val) + ) + | CmpGreaterEq (exp_1, exp_2) -> ( + let exp_1val = match evaluate mem exp_1 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + let exp_2val = match evaluate mem exp_2 with + IntegerPermitted x -> x + | _ -> raise (WrongType ("Value is not an integer")) + in + BooleanPermitted (exp_1val >= exp_2val) + ) + | IfThenElse (guard, if_exp, else_exp) -> + let bguard = ( + match evaluate mem guard with + BooleanPermitted b -> b + | _ -> raise (WrongType ("Value in if guard is not a boolean")) + ) in + if bguard then + evaluate mem if_exp + else + evaluate mem else_exp + | LetIn (x, xval, rest) -> + let evalxval = evaluate mem xval in + let mem2 = {assignments = VariableMap.add x evalxval mem.assignments} in + evaluate mem2 rest + | LetFun (f, xs, fbody, rest) -> + let mem2 = { + assignments = + VariableMap.add + f + (FunctionPermitted + { inputList = xs; + body = fbody; + assignments = mem.assignments; + recursiveness = Some f}) + mem.assignments} + in + evaluate mem2 rest + + +let reduce (program: t_exp) (iin : int) = + let program' = (Application (program, [(Integer iin)])) in + let mem : memory = {assignments = VariableMap.empty} in + match (evaluate mem program') with + IntegerPermitted a -> a + | _ -> raise (WrongType ("Main function doesn't return an integer")) diff --git a/lib/miniFun.mli b/lib/miniFun.mli new file mode 100644 index 0000000..9960f52 --- /dev/null +++ b/lib/miniFun.mli @@ -0,0 +1,51 @@ +type variable = string + +module VariableMap : Map.S with type key = variable + +type t_exp = + Integer of int + | Boolean of bool + | Variable of variable + | Function of variable list * t_exp + | Application of t_exp * t_exp list + | Plus of t_exp * t_exp + | Minus of t_exp * t_exp + | Times of t_exp * t_exp + | Division of t_exp * t_exp + | Modulo of t_exp * t_exp + | Power of t_exp * t_exp + | PowerMod of t_exp * t_exp * t_exp + | Rand of t_exp + | BAnd of t_exp * t_exp + | BOr of t_exp * t_exp + | BNot of t_exp + | Cmp of t_exp * t_exp + | CmpLess of t_exp * t_exp + | CmpLessEq of t_exp * t_exp + | CmpGreater of t_exp * t_exp + | CmpGreaterEq of t_exp * t_exp + | IfThenElse of t_exp * t_exp * t_exp + | LetIn of variable * t_exp * t_exp + | LetFun of variable * variable list * t_exp * t_exp + +type permittedValues = + IntegerPermitted of int + | BooleanPermitted of bool + | FunctionPermitted of closure +and closure = { + inputList: variable list; + body: t_exp; + assignments: permittedValues VariableMap.t; + recursiveness: variable option +} + +type memory = { + assignments: permittedValues VariableMap.t +} + +exception AbsentAssignment of string +exception WrongType of string +exception DivisionByZero of string +exception WrongAriety of string + +val reduce : t_exp -> int -> int diff --git a/test/dune b/test/dune index 2dae150..8d5c71b 100644 --- a/test/dune +++ b/test/dune @@ -1,3 +1,7 @@ (test (name testingImp) (libraries lang)) + +(test + (name testingFun) + (libraries lang)) \ No newline at end of file diff --git a/test/testingFun.expected b/test/testingFun.expected new file mode 100644 index 0000000..958bc3e --- /dev/null +++ b/test/testingFun.expected @@ -0,0 +1,7 @@ +1 +1 +5 +6 +4 +-4 +55 diff --git a/test/testingFun.ml b/test/testingFun.ml new file mode 100644 index 0000000..0282d27 --- /dev/null +++ b/test/testingFun.ml @@ -0,0 +1,107 @@ +open Lang.MiniFun + +(* -------------------------------------------------------------------------- *) +(* Identity program *) +let program = + Function + (["a"], + (Variable "a") + ) +;; + +Printf.printf "%d\n" (reduce program 1) + +(* -------------------------------------------------------------------------- *) +(* Constant program *) +let program = + Function + (["a"], + (Integer 1) + ) +;; + +Printf.printf "%d\n" (reduce program 10) + +(* -------------------------------------------------------------------------- *) +(* Partial application of function program *) +let program = + LetIn + ("f", + (Function (["x"; "y"], Plus (Variable "x", Variable "y"))), + (Application (Variable "f", [Integer 3])) + ) +;; + +Printf.printf "%d\n" (reduce program 2) + +(* -------------------------------------------------------------------------- *) +(* Partial application of function program *) +let program = + LetFun + ("f", + ["x"], + (Function (["y"], Plus (Variable "x", Variable "y"))), + (Application (Variable "f", [Integer 3])) + ) +;; + +Printf.printf "%d\n" (reduce program 3) + +(* -------------------------------------------------------------------------- *) +(* Passing functions to functions program *) +let program = + LetIn + ("f", + (Function ( + ["z"], + (Function ( + ["y"], + Function ( + ["x"], + (IfThenElse ( + CmpLess (Variable "x", Integer 0), + (Application (Variable "y", [Variable "x"])), + (Application (Variable "z", [Variable "x"])) + ))) + )) + )), + (Application + ( + (Application + (Variable "f", + [Function (["x"], Plus (Variable "x", Integer 1))] + ) + ), + [Function (["x"], Minus (Variable "x", Integer 1))] + ) + ) + ) +;; + +Printf.printf "%d\n" (reduce program (3)); +Printf.printf "%d\n" (reduce program (-3)) + +(* -------------------------------------------------------------------------- *) +(* Recursive function program *) +let program = + LetFun + ("f", + ["x"], + (IfThenElse (CmpLess (Variable "x", Integer 2),Integer 1, Plus (Variable "x", Application (Variable "f", [Minus (Variable "x", Integer 1)])))), + (Variable "f") + ) +;; + +Printf.printf "%d\n" (reduce program 10) + +(* -------------------------------------------------------------------------- *) +(* Scope program *) +let program = + LetIn + ("f", + (LetIn ("a", Integer 1, (Function (["y"], Plus (Variable "y", Variable "a"))))), + (LetIn ("a", Integer 2, Variable "f")) + ) +;; + +Printf.printf "%d\n" (reduce program 4) diff --git a/test/testingImp.expected b/test/testingImp.expected new file mode 100644 index 0000000..b594dc5 --- /dev/null +++ b/test/testingImp.expected @@ -0,0 +1,9 @@ +1 +The variable y is not defined. +3628800 +351 +35553600 +true +4807526976 +0 +1 diff --git a/test/testingImp.ml b/test/testingImp.ml new file mode 100644 index 0000000..7c0a39f --- /dev/null +++ b/test/testingImp.ml @@ -0,0 +1,222 @@ +open Lang.MiniImp + +(* -------------------------------------------------------------------------- *) +(* Identity program *) +let program = + Main + ("a", + "b", + (Assignment ("b", (Variable "a"))) + ) +;; + +Printf.printf "%d\n" (reduce 1 program) + +(* -------------------------------------------------------------------------- *) +(* y not defined program *) +let program = + Main + ("a", + "b", + (Sequence ( + (Assignment ("x", (Integer 1))), + (Assignment ("b", + (Plus ((Plus (Variable "a", Variable "x")), (Variable "y"))))) + ) + ) + ) +;; + +try + Printf.printf "%d\n" (reduce 100 program) +with AbsentAssignment s -> + Printf.printf "%s\n" s +;; + +(* -------------------------------------------------------------------------- *) +(* factorial program *) +let program = + Main + ("a", + "b", + (Sequence ( + (Assignment ("b", (Integer 1))), + (For ( + (Assignment ("i", (Integer 1))), + (BCmpLessEq (Variable "i", Variable "a")), + (Assignment ("i", (Plus ((Variable "i"), (Integer 1))))), + (Assignment ("b", (Times (Variable "b", Variable "i")))) + ) + ) + ) + ) + ) +;; + +Printf.printf "%d\n" (reduce 10 program) +;; + +(* -------------------------------------------------------------------------- *) +(* hailstone sequence's lenght program *) +let program = + Main + ("a", + "b", + (Sequence ( + (Assignment ("b", (Integer 1))), + (While ( + (BNot (BCmp ((Variable "a"), (Integer 1)))), + (Sequence ( + (Assignment ("b", (Plus (Variable "b", Integer 1)))), + (If ( + (BCmp (Modulo (Variable "a", Integer 2), Integer 1)), + (Assignment ("a", Plus (Times (Integer 3, Variable "a"), Integer 1))), + (Assignment ("a", Division (Variable "a", Integer 2))) + )) + )) + )) + )) + ) +;; + +Printf.printf "%d\n" (reduce 77031 program) +;; + +(* -------------------------------------------------------------------------- *) +(* sum multiples of 3 and 5 program *) +let program = + Main + ("a", + "b", + (Sequence ( + (Assignment ("b", (Integer 0))), + (For ( + (Assignment ("i", Integer 0)), + (BCmpLess (Variable "i", Variable "a")), + (Assignment ("i", Plus (Variable "i", Integer 1))), + (If ( + (BOr ((BCmp (Modulo (Variable "i", Integer 3), Integer 0)), + (BCmp (Modulo (Variable "i", Integer 5), Integer 0)))), + (Assignment ("b", Plus (Variable "b", Variable "i"))), + (Skip) + )) + )) + )) + ) +;; + +Printf.printf "%d\n" (reduce 12345 program) +;; + +(* -------------------------------------------------------------------------- *) +(* rand program *) +let program = + Main + ("a", + "b", + (Assignment ("b", Rand (Variable "a"))) + ) +;; + +Printf.printf "%b\n" ((reduce 10 program) < 10) +;; + +(* -------------------------------------------------------------------------- *) +(* fibonacci program *) +let program = + Main + ("n", + "fnext", + (Sequence ( + Sequence ( + (Assignment ("fnow", Integer 0)), + (Assignment ("fnext", Integer 1)) + ), + (While ( + (BCmpGreater (Variable "n", Integer 1)), + (Sequence ( + (Sequence ( + (Assignment ("tmp", Plus (Variable "fnow", Variable "fnext"))), + (Assignment ("fnow", Variable "fnext")) + )), + (Sequence ( + (Assignment ("fnext", Variable "tmp")), + (Assignment ("n", Minus (Variable "n", Integer 1))) + )) + )))) + )) + ) +;; + +Printf.printf "%d\n" (reduce 48 program) +;; + +(* -------------------------------------------------------------------------- *) +(* Miller-Rabin primality test program *) +let program = + Main + ("n", + "result", + Sequence ( + (Assignment ("result", Integer 0)), + (Sequence ( + (Sequence ( + (Assignment ("s", Integer 0)), + (While ( + (BCmp (Integer 0, + Modulo ( + Division ( + (Minus (Variable "n", Integer 1)), + (Power (Integer 2, Variable "s"))), + (Integer 2) + ) + ) + ), + (Assignment ("s", Plus (Variable "s", Integer 1))) + )) + )), + (Sequence ( + (Assignment ("d", Division (Minus (Variable "n", Integer 1), Power (Integer 2, Variable "s")))), + (For ( + (Assignment ("i", Integer 20)), + (BCmpGreater (Variable "i", Integer 0)), + (Assignment ("i", Minus (Variable "i", Integer 1))), + (Sequence ( + Sequence ( + (Assignment ("a", Plus (Rand (Minus (Variable "n", Integer 4)), Integer 2))), + (Assignment ("x", PowerMod (Variable "a", Variable "d", Variable "n")))), + Sequence ( + (For ( + (Assignment ("j", Integer 0)), + (BCmpLess (Variable "j", Variable "s")), + (Assignment ("j", Plus (Variable "j", Integer 1))), + (Sequence ( + Sequence ( + (Assignment ("y", PowerMod (Variable "x", Integer 2, Variable "n"))), + (If ( + (BAnd (BAnd (BCmp (Variable "y", Integer 1), BNot (BCmp (Variable "x", Integer 1))), BNot (BCmp (Variable "x", Minus (Variable "n", Integer 1))))), + (Assignment ("result", Integer 1)), + (Skip) + ))), + (Assignment ("x", Variable "y")) + )) + )), + (If ( + (BNot (BCmp (Variable "y", Integer 1))), + (Assignment ("result", Integer 1)), + (Skip) + ))) + )) + )) + )) + )) + ) + ) +;; + +(* should return 0 because prime *) +Printf.printf "%d\n" (reduce 179424673 program) +;; +(* sould return 1 because not prime *) +Printf.printf "%d\n" (reduce 179424675 program) +;;