Adding tests, adding miniFun implementation
This commit is contained in:
223
bin/main.ml
223
bin/main.ml
@ -1,222 +1 @@
|
|||||||
open Lang.MiniImp
|
print_endline "Hello!"
|
||||||
|
|
||||||
(* -------------------------------------------------------------------------- *)
|
|
||||||
(* 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)
|
|
||||||
;;
|
|
||||||
|
|||||||
358
lib/miniFun.ml
Normal file
358
lib/miniFun.ml
Normal file
@ -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"))
|
||||||
51
lib/miniFun.mli
Normal file
51
lib/miniFun.mli
Normal file
@ -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
|
||||||
@ -1,3 +1,7 @@
|
|||||||
(test
|
(test
|
||||||
(name testingImp)
|
(name testingImp)
|
||||||
(libraries lang))
|
(libraries lang))
|
||||||
|
|
||||||
|
(test
|
||||||
|
(name testingFun)
|
||||||
|
(libraries lang))
|
||||||
7
test/testingFun.expected
Normal file
7
test/testingFun.expected
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
1
|
||||||
|
1
|
||||||
|
5
|
||||||
|
6
|
||||||
|
4
|
||||||
|
-4
|
||||||
|
55
|
||||||
107
test/testingFun.ml
Normal file
107
test/testingFun.ml
Normal file
@ -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)
|
||||||
9
test/testingImp.expected
Normal file
9
test/testingImp.expected
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
1
|
||||||
|
The variable y is not defined.
|
||||||
|
3628800
|
||||||
|
351
|
||||||
|
35553600
|
||||||
|
true
|
||||||
|
4807526976
|
||||||
|
0
|
||||||
|
1
|
||||||
222
test/testingImp.ml
Normal file
222
test/testingImp.ml
Normal file
@ -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)
|
||||||
|
;;
|
||||||
Reference in New Issue
Block a user