Semantics for RISC code
This commit is contained in:
3
bin/dune
3
bin/dune
@ -4,6 +4,7 @@
|
|||||||
(libraries exercises
|
(libraries exercises
|
||||||
miniImp
|
miniImp
|
||||||
miniFun
|
miniFun
|
||||||
|
cfg
|
||||||
utility)
|
utility)
|
||||||
(package miniFun)
|
(package miniFun)
|
||||||
(modes byte exe)
|
(modes byte exe)
|
||||||
@ -25,4 +26,4 @@
|
|||||||
clap)
|
clap)
|
||||||
(package miniImp)
|
(package miniImp)
|
||||||
(modes byte exe)
|
(modes byte exe)
|
||||||
)
|
)
|
||||||
|
|||||||
44
bin/main.ml
44
bin/main.ml
@ -1,35 +1,37 @@
|
|||||||
open MiniImp
|
open MiniImp
|
||||||
|
|
||||||
let () =
|
let colorred s =
|
||||||
(* let program = "def main with input x output y as *)
|
"\027[31m" ^ s ^ "\027[0m"
|
||||||
(* x := 2; *)
|
|
||||||
(* if y < 0 then ( *)
|
|
||||||
(* y := x + 3; *)
|
|
||||||
(* x := y; *)
|
|
||||||
(* ) else *)
|
|
||||||
(* x := 1 - y;" in *)
|
|
||||||
|
|
||||||
let program = "def main with input x output y as
|
let () =
|
||||||
x := 2;
|
let program = "
|
||||||
if y < 0 then (
|
def main with input a output b as
|
||||||
y := x + 3;
|
b := 1;
|
||||||
if x > 0 then
|
for (i := 1, i <= a, i := i + 1) do
|
||||||
x := y;
|
b := b * i;
|
||||||
else
|
"
|
||||||
x := y + 1;
|
in
|
||||||
) else
|
|
||||||
x := 1 - y;" in
|
Printf.printf "%s\n%s\n" (colorred "Program is") program;
|
||||||
|
|
||||||
let get_result x = Lexing.from_string x |> Parser.prg Lexer.lex in
|
let get_result x = Lexing.from_string x |> Parser.prg Lexer.lex in
|
||||||
|
|
||||||
let p = get_result program in
|
let p = get_result program in
|
||||||
|
|
||||||
let convertedcfg = CfgImp.convert_io p 3 in
|
Format.printf "%s\n%a\n@?" (colorred "AST is") Types.pp_p_exp p;
|
||||||
|
|
||||||
Printf.printf "%a" CfgImp.SSCfg.pp convertedcfg;
|
let convertedcfg = CfgImp.convert_io 10 p in
|
||||||
|
|
||||||
|
Printf.printf "%s\n%a" (colorred "Converted CFG is") CfgImp.SSCfg.pp convertedcfg;
|
||||||
|
|
||||||
let convertedrisccfg = CfgRISC.convert convertedcfg in
|
let convertedrisccfg = CfgRISC.convert convertedcfg in
|
||||||
|
|
||||||
|
Printf.printf "%s\n%a" (colorred "Converted RISC CFG is") CfgRISC.RISCCfg.pp convertedrisccfg;
|
||||||
|
|
||||||
let risc = RISC.convert convertedrisccfg in
|
let risc = RISC.convert convertedrisccfg in
|
||||||
|
|
||||||
Printf.printf "%a" RISC.RISCAssembly.pp risc
|
Printf.printf "%s\n%a" (colorred "RISC code is") RISC.RISCAssembly.pp risc;
|
||||||
|
|
||||||
|
let computerisc = RISCSemantics.reduce risc in
|
||||||
|
|
||||||
|
Printf.printf "%s\n%d\n" (colorred "Output of RISC code is") computerisc;
|
||||||
|
|||||||
@ -179,13 +179,15 @@ and convert_a (prg: Types.a_exp) : SimpleStatements.simpleArithmetic =
|
|||||||
| Division (a1, a2) -> SimpleDivision (convert_a a1, convert_a a2)
|
| Division (a1, a2) -> SimpleDivision (convert_a a1, convert_a a2)
|
||||||
| Modulo (a1, a2) -> SimpleModulo (convert_a a1, convert_a a2)
|
| Modulo (a1, a2) -> SimpleModulo (convert_a a1, convert_a a2)
|
||||||
| Power (a1, a2) -> SimplePower (convert_a a1, convert_a a2)
|
| Power (a1, a2) -> SimplePower (convert_a a1, convert_a a2)
|
||||||
| PowerMod (a1, a2, a3) -> SimplePowerMod (convert_a a1, convert_a a2, convert_a a3)
|
| PowerMod (_) -> failwith "Cannot convert PowerMod into Simple Instruction"
|
||||||
| Rand (a) -> SimpleRand (convert_a a)
|
| Rand (a) -> SimpleRand (convert_a a)
|
||||||
|
|
||||||
let convert (prg: Types.p_exp) : SSCfg.t =
|
let convert (prg: Types.p_exp) : SSCfg.t =
|
||||||
|
let prg = ReplacePowerMod.rewrite_instructions prg in
|
||||||
match prg with
|
match prg with
|
||||||
| Main (i, o, exp) ->
|
| Main (i, o, exp) ->
|
||||||
{(convert_c SSCfg.empty exp) with inputOutputVar = Some (i, o)}
|
{(convert_c SSCfg.empty exp) with inputOutputVar = Some (i, o)}
|
||||||
|
|
||||||
let convert_io (prg: Types.p_exp) (i: int) : SSCfg.t =
|
let convert_io (i: int) (prg: Types.p_exp) : SSCfg.t =
|
||||||
|
let prg = ReplacePowerMod.rewrite_instructions prg in
|
||||||
{(convert prg) with inputVal = Some i}
|
{(convert prg) with inputVal = Some i}
|
||||||
|
|||||||
@ -32,4 +32,4 @@ end
|
|||||||
module SSCfg : Cfg.C with type elt = SimpleStatements.t
|
module SSCfg : Cfg.C with type elt = SimpleStatements.t
|
||||||
|
|
||||||
val convert : Types.p_exp -> SSCfg.t
|
val convert : Types.p_exp -> SSCfg.t
|
||||||
val convert_io : Types.p_exp -> int -> SSCfg.t
|
val convert_io : int -> Types.p_exp -> SSCfg.t
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
module RISCSimpleStatements = struct
|
module RISCSimpleStatements = struct
|
||||||
type register = {
|
type register = {
|
||||||
index: int
|
index: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type t =
|
type t =
|
||||||
@ -48,12 +48,12 @@ module RISCSimpleStatements = struct
|
|||||||
let rec pp_t (ppf: out_channel) (v: t) : unit =
|
let rec pp_t (ppf: out_channel) (v: t) : unit =
|
||||||
match v with
|
match v with
|
||||||
Nop -> Printf.fprintf ppf "Nop"
|
Nop -> Printf.fprintf ppf "Nop"
|
||||||
| BRegOp (b, r1, r2, r3) -> Printf.fprintf ppf "%a r%d r%d => r%d" pp_brop b r1.index r2.index r3.index
|
| BRegOp (b, r1, r2, r3) -> Printf.fprintf ppf "%a r%s r%s => r%s" pp_brop b r1.index r2.index r3.index
|
||||||
| BImmOp (b, r1, i, r3) -> Printf.fprintf ppf "%a r%d %d => r%d" pp_biop b r1.index i r3.index
|
| BImmOp (b, r1, i, r3) -> Printf.fprintf ppf "%a r%s %d => r%s" pp_biop b r1.index i r3.index
|
||||||
| URegOp (u, r1, r2) -> Printf.fprintf ppf "%a r%d => r%d" pp_urop u r1.index r2.index
|
| URegOp (u, r1, r2) -> Printf.fprintf ppf "%a r%s => r%s" pp_urop u r1.index r2.index
|
||||||
| Load (r1, r2) -> Printf.fprintf ppf "Load r%d => r%d" r1.index r2.index
|
| Load (r1, r2) -> Printf.fprintf ppf "Load r%s => r%s" r1.index r2.index
|
||||||
| LoadI (r2, i) -> Printf.fprintf ppf "LoadI %d => r%d" i r2.index
|
| LoadI (r2, i) -> Printf.fprintf ppf "LoadI %d => r%s" i r2.index
|
||||||
| Store (r1, r2) -> Printf.fprintf ppf "Store r%d => r%d" r1.index r2.index
|
| Store (r1, r2) -> Printf.fprintf ppf "Store r%s => r%s" r1.index r2.index
|
||||||
and pp_brop (ppf: out_channel) (v: brop) : unit =
|
and pp_brop (ppf: out_channel) (v: brop) : unit =
|
||||||
match v with
|
match v with
|
||||||
Add -> Printf.fprintf ppf "Add"
|
Add -> Printf.fprintf ppf "Add"
|
||||||
@ -101,25 +101,34 @@ module RISCCfg = Cfg.Make(RISCSimpleStatements)
|
|||||||
let globalcounter = ref 0
|
let globalcounter = ref 0
|
||||||
module RegisterMap = struct
|
module RegisterMap = struct
|
||||||
type m = {
|
type m = {
|
||||||
assignments: int Types.VariableMap.t
|
assignments: RISCSimpleStatements.register Types.VariableMap.t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let set_register (x: Types.variable) (v: RISCSimpleStatements.register) (m: m)
|
||||||
|
: m =
|
||||||
|
{assignments = Types.VariableMap.add x v m.assignments}
|
||||||
|
|
||||||
let get_or_set_register (x: Types.variable) (m: m)
|
let get_or_set_register (x: Types.variable) (m: m)
|
||||||
: RISCSimpleStatements.register * m =
|
: RISCSimpleStatements.register * m =
|
||||||
match Types.VariableMap.find_opt x m.assignments with
|
match Types.VariableMap.find_opt x m.assignments with
|
||||||
None ->
|
None -> (
|
||||||
( globalcounter := !globalcounter + 1;
|
globalcounter := !globalcounter + 1;
|
||||||
({index = !globalcounter},
|
({index = string_of_int !globalcounter},
|
||||||
{assignments = Types.VariableMap.add x !globalcounter m.assignments}))
|
{assignments =
|
||||||
| Some i -> ({index = i}, m)
|
Types.VariableMap.add x
|
||||||
|
({index = (string_of_int !globalcounter)}: RISCSimpleStatements.register)
|
||||||
|
m.assignments}))
|
||||||
|
| Some i -> (i, m)
|
||||||
|
|
||||||
let get_fresh_register (m: m)
|
let get_fresh_register (m: m)
|
||||||
: RISCSimpleStatements.register * m * Types.variable =
|
: RISCSimpleStatements.register * m * Types.variable =
|
||||||
globalcounter := !globalcounter + 1;
|
globalcounter := !globalcounter + 1;
|
||||||
let freshvariable = string_of_int !globalcounter in
|
let freshvariable = string_of_int !globalcounter in
|
||||||
({index = !globalcounter},
|
({index = string_of_int !globalcounter},
|
||||||
{assignments =
|
{assignments =
|
||||||
Types.VariableMap.add freshvariable !globalcounter m.assignments},
|
Types.VariableMap.add freshvariable
|
||||||
|
({index = string_of_int !globalcounter}: RISCSimpleStatements.register)
|
||||||
|
m.assignments},
|
||||||
freshvariable)
|
freshvariable)
|
||||||
|
|
||||||
let empty : m =
|
let empty : m =
|
||||||
@ -436,7 +445,7 @@ and c_ss_sa
|
|||||||
match ss with
|
match ss with
|
||||||
SimpleVariable (x) -> (
|
SimpleVariable (x) -> (
|
||||||
let r1, m = RegisterMap.get_or_set_register x m in
|
let r1, m = RegisterMap.get_or_set_register x m in
|
||||||
(convertedcode @ [Load (r1, register)], m)
|
(convertedcode @ [URegOp (Copy, r1, register)], m)
|
||||||
)
|
)
|
||||||
| SimpleInteger (i) -> (
|
| SimpleInteger (i) -> (
|
||||||
(convertedcode @ [LoadI (register, i)], m)
|
(convertedcode @ [LoadI (register, i)], m)
|
||||||
@ -695,7 +704,9 @@ and c_ss_sa
|
|||||||
(convertedcode @ [BRegOp (Pow, partialresreg1, partialresreg2, register)], m)
|
(convertedcode @ [BRegOp (Pow, partialresreg1, partialresreg2, register)], m)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
| SimplePowerMod (_a1, _a2, _a3) -> failwith "Not implemented Powermod"
|
| SimplePowerMod (_a1, _a2, _a3) -> (
|
||||||
|
failwith "not implemented"
|
||||||
|
)
|
||||||
| SimpleRand (a) -> (
|
| SimpleRand (a) -> (
|
||||||
let partialresreg, m, _partialresvar = RegisterMap.get_fresh_register m in
|
let partialresreg, m, _partialresvar = RegisterMap.get_fresh_register m in
|
||||||
let convertedcode, m = c_ss_sa a m convertedcode partialresreg in
|
let convertedcode, m = c_ss_sa a m convertedcode partialresreg in
|
||||||
@ -713,9 +724,7 @@ let convert_ss
|
|||||||
association between variables and registers so we choose a fold instead of
|
association between variables and registers so we choose a fold instead of
|
||||||
a mapreduce *)
|
a mapreduce *)
|
||||||
let instructions, m = List.fold_left
|
let instructions, m = List.fold_left
|
||||||
(fun (convertedcode, m) code -> (
|
(fun (convertedcode, m) code -> c_ss_t code m convertedcode)
|
||||||
Printf.printf "considering: %a\n" CfgImp.SimpleStatements.pp code;
|
|
||||||
c_ss_t code m convertedcode))
|
|
||||||
([], m) value
|
([], m) value
|
||||||
in
|
in
|
||||||
(Cfg.NodeMap.add node instructions risccode, m)
|
(Cfg.NodeMap.add node instructions risccode, m)
|
||||||
@ -744,13 +753,23 @@ let convert (prg: CfgImp.SSCfg.t) : RISCCfg.t =
|
|||||||
initial: Cfg.Node.t option;
|
initial: Cfg.Node.t option;
|
||||||
terminal: Cfg.Node.t option;
|
terminal: Cfg.Node.t option;
|
||||||
content: CfgImp.SimpleStatements.t list Cfg.NodeMap.t
|
content: CfgImp.SimpleStatements.t list Cfg.NodeMap.t
|
||||||
} -> { empty = empty;
|
} ->
|
||||||
nodes = nodes;
|
let initial_bindings =
|
||||||
edges = edges;
|
match inputOutputVar with
|
||||||
reverseEdges = reverseEdges;
|
| Some (i, o) ->
|
||||||
inputVal = inputVal;
|
RegisterMap.empty |>
|
||||||
inputOutputVar = inputOutputVar;
|
RegisterMap.set_register i {index = "in"} |>
|
||||||
initial = initial;
|
RegisterMap.set_register o {index = "out"}
|
||||||
terminal = terminal;
|
| None ->
|
||||||
content = helper content RegisterMap.empty;
|
RegisterMap.empty
|
||||||
}
|
in
|
||||||
|
{ empty = empty;
|
||||||
|
nodes = nodes;
|
||||||
|
edges = edges;
|
||||||
|
reverseEdges = reverseEdges;
|
||||||
|
inputVal = inputVal;
|
||||||
|
inputOutputVar = inputOutputVar;
|
||||||
|
initial = initial;
|
||||||
|
terminal = terminal;
|
||||||
|
content = helper content initial_bindings;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
module RISCSimpleStatements : sig
|
module RISCSimpleStatements : sig
|
||||||
type register = {
|
type register = {
|
||||||
index: int
|
index: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type t =
|
type t =
|
||||||
|
|||||||
@ -6,11 +6,10 @@ let nextLabel () : string =
|
|||||||
|
|
||||||
module RISCAssembly = struct
|
module RISCAssembly = struct
|
||||||
type register = {
|
type register = {
|
||||||
index : int
|
index : string
|
||||||
}
|
}
|
||||||
|
|
||||||
type label =
|
type label = string
|
||||||
string
|
|
||||||
|
|
||||||
type risci =
|
type risci =
|
||||||
| Nop
|
| Nop
|
||||||
@ -56,20 +55,23 @@ module RISCAssembly = struct
|
|||||||
| Copy
|
| Copy
|
||||||
| Rand
|
| Rand
|
||||||
|
|
||||||
type t = risci list
|
type t = {
|
||||||
|
code : risci list;
|
||||||
|
inputval: int option
|
||||||
|
}
|
||||||
|
|
||||||
let pp (ppf: out_channel) (t: t) : unit =
|
let pp_risci (ppf: out_channel) (v: risci) : unit =
|
||||||
let rec pp_risci (ppf: out_channel) (v: risci) : unit =
|
let rec pp_risci (ppf: out_channel) (v: risci) : unit =
|
||||||
match v with
|
match v with
|
||||||
Nop -> Printf.fprintf ppf "\tNop\n"
|
Nop -> Printf.fprintf ppf "\tNop\n"
|
||||||
| BRegOp (b, r1, r2, r3) -> Printf.fprintf ppf "\t%a r%d r%d => r%d\n" pp_brop b r1.index r2.index r3.index
|
| BRegOp (b, r1, r2, r3) -> Printf.fprintf ppf "\t%a r%s r%s => r%s\n" pp_brop b r1.index r2.index r3.index
|
||||||
| BImmOp (b, r1, i, r3) -> Printf.fprintf ppf "\t%a r%d %d => r%d\n" pp_biop b r1.index i r3.index
|
| BImmOp (b, r1, i, r3) -> Printf.fprintf ppf "\t%a r%s %d => r%s\n" pp_biop b r1.index i r3.index
|
||||||
| URegOp (u, r1, r2) -> Printf.fprintf ppf "\t%a r%d => r%d\n" pp_urop u r1.index r2.index
|
| URegOp (u, r1, r2) -> Printf.fprintf ppf "\t%a r%s => r%s\n" pp_urop u r1.index r2.index
|
||||||
| Load (r1, r2) -> Printf.fprintf ppf "\tLoad r%d => r%d\n" r1.index r2.index
|
| Load (r1, r2) -> Printf.fprintf ppf "\tLoad r%s => r%s\n" r1.index r2.index
|
||||||
| LoadI (r2, i) -> Printf.fprintf ppf "\tLoadI %d => r%d\n" i r2.index
|
| LoadI (r2, i) -> Printf.fprintf ppf "\tLoadI %d => r%s\n" i r2.index
|
||||||
| Store (r1, r2) -> Printf.fprintf ppf "\tStore r%d => r%d\n" r1.index r2.index
|
| Store (r1, r2) -> Printf.fprintf ppf "\tStore r%s => r%s\n" r1.index r2.index
|
||||||
| Jump (label) -> Printf.fprintf ppf "\tJump %s\n" label
|
| Jump (label) -> Printf.fprintf ppf "\tJump %s\n" label
|
||||||
| CJump (r, l1, l2) -> Printf.fprintf ppf "\tCJump r%d => %s, %s\n" r.index l1 l2
|
| CJump (r, l1, l2) -> Printf.fprintf ppf "\tCJump r%s => %s, %s\n" r.index l1 l2
|
||||||
| Label (label) -> Printf.fprintf ppf "%s:" label
|
| Label (label) -> Printf.fprintf ppf "%s:" label
|
||||||
and pp_brop (ppf: out_channel) (v: brop) : unit =
|
and pp_brop (ppf: out_channel) (v: brop) : unit =
|
||||||
match v with
|
match v with
|
||||||
@ -107,10 +109,18 @@ module RISCAssembly = struct
|
|||||||
| Copy -> Printf.fprintf ppf "Copy"
|
| Copy -> Printf.fprintf ppf "Copy"
|
||||||
| Rand -> Printf.fprintf ppf "Rand"
|
| Rand -> Printf.fprintf ppf "Rand"
|
||||||
in
|
in
|
||||||
List.iter (pp_risci ppf) t
|
pp_risci ppf v
|
||||||
|
|
||||||
|
let pp (ppf: out_channel) (t: t) : unit =
|
||||||
|
Printf.fprintf ppf "Input Val: ";
|
||||||
|
match t.inputval with
|
||||||
|
None -> Printf.fprintf ppf "None\n"
|
||||||
|
| Some i -> Printf.fprintf ppf "Some %d\n" i;
|
||||||
|
Printf.fprintf ppf "Code:\n";
|
||||||
|
List.iter (pp_risci ppf) t.code
|
||||||
end
|
end
|
||||||
|
|
||||||
let convert_cfgrisc_risci (i: CfgRISC.RISCSimpleStatements.t list) : (RISCAssembly.t) =
|
let convert_cfgrisc_risci (i: CfgRISC.RISCSimpleStatements.t list) : (RISCAssembly.risci list) =
|
||||||
let rec helper (i: CfgRISC.RISCSimpleStatements.t) : RISCAssembly.risci =
|
let rec helper (i: CfgRISC.RISCSimpleStatements.t) : RISCAssembly.risci =
|
||||||
match i with
|
match i with
|
||||||
| Nop -> Nop
|
| Nop -> Nop
|
||||||
@ -196,7 +206,7 @@ let rec helper
|
|||||||
(prg: CfgRISC.RISCCfg.t)
|
(prg: CfgRISC.RISCCfg.t)
|
||||||
(currentnode: Cfg.Node.t)
|
(currentnode: Cfg.Node.t)
|
||||||
(alreadyVisited: Cfg.Node.t list)
|
(alreadyVisited: Cfg.Node.t list)
|
||||||
: RISCAssembly.t * Cfg.Node.t list =
|
: (RISCAssembly.risci list) * (Cfg.Node.t list) =
|
||||||
(* takes the program, the current node and a list of already visited nodes to
|
(* takes the program, the current node and a list of already visited nodes to
|
||||||
compute the linearized three address instructions and the list of
|
compute the linearized three address instructions and the list of
|
||||||
previoulsy visited nodes plus the newly visited nodes. Stops as soon if
|
previoulsy visited nodes plus the newly visited nodes. Stops as soon if
|
||||||
@ -235,14 +245,14 @@ let rec helper
|
|||||||
| BImmOp (_, _, _, r)
|
| BImmOp (_, _, _, r)
|
||||||
| URegOp (_, _, r)
|
| URegOp (_, _, r)
|
||||||
| Load (_, r)
|
| Load (_, r)
|
||||||
| LoadI (r, _) -> (([Label label1] : RISCAssembly.t) @
|
| LoadI (r, _) -> (([Label label1] : RISCAssembly.risci list) @
|
||||||
currentcode @
|
currentcode @
|
||||||
([CJump (r, label2, label3); Label label2] : RISCAssembly.t) @
|
([CJump (r, label2, label3); Label label2] : RISCAssembly.risci list) @
|
||||||
res1 @
|
res1 @
|
||||||
([Jump label1; Label label3] : RISCAssembly.t) @
|
([Jump label1; Label label3] : RISCAssembly.risci list) @
|
||||||
res2
|
res2
|
||||||
, vis2)
|
, vis2)
|
||||||
| _ -> failwith "Missing instruction"
|
| _ -> failwith "Missing instruction at branch"
|
||||||
else (* if branches, three labels are necessary *)
|
else (* if branches, three labels are necessary *)
|
||||||
let label1 = nextLabel () in
|
let label1 = nextLabel () in
|
||||||
let label2 = nextLabel () in
|
let label2 = nextLabel () in
|
||||||
@ -257,19 +267,20 @@ let rec helper
|
|||||||
| URegOp (_, _, r)
|
| URegOp (_, _, r)
|
||||||
| Load (_, r)
|
| Load (_, r)
|
||||||
| LoadI (r, _) -> (currentcode @
|
| LoadI (r, _) -> (currentcode @
|
||||||
([CJump (r, label1, label2); Label label1] : RISCAssembly.t) @
|
([CJump (r, label1, label2); Label label1] : RISCAssembly.risci list) @
|
||||||
res1 @
|
res1 @
|
||||||
([Jump label3; Label label2] : RISCAssembly.t) @
|
([Jump label3; Label label2] : RISCAssembly.risci list) @
|
||||||
res2 @
|
res2 @
|
||||||
([Label label3] : RISCAssembly.t) @
|
([Label label3] : RISCAssembly.risci list) @
|
||||||
res3
|
res3
|
||||||
, vis3)
|
, vis3)
|
||||||
| _ -> failwith "Missing instruction"
|
| _ -> failwith "Missing instruction at branch"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
| None -> (currentcode, currentnode :: alreadyVisited)
|
| None -> (currentcode, currentnode :: alreadyVisited)
|
||||||
)
|
)
|
||||||
|
|
||||||
let convert (prg: CfgRISC.RISCCfg.t) : RISCAssembly.t =
|
let convert (prg: CfgRISC.RISCCfg.t) : RISCAssembly.t =
|
||||||
let res, _ = helper prg (Option.get prg.initial) [] in
|
{code = (helper prg (Option.get prg.initial) [] |> fst |>
|
||||||
res
|
List.append ([Label "main"] : RISCAssembly.risci list));
|
||||||
|
inputval = prg.inputVal}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
module RISCAssembly : sig
|
module RISCAssembly : sig
|
||||||
type register = {
|
type register = {
|
||||||
index : int
|
index : string
|
||||||
}
|
}
|
||||||
|
|
||||||
type label
|
type label = string
|
||||||
type risci =
|
type risci =
|
||||||
| Nop
|
| Nop
|
||||||
| BRegOp of brop * register * register * register
|
| BRegOp of brop * register * register * register
|
||||||
@ -48,8 +48,12 @@ module RISCAssembly : sig
|
|||||||
| Copy
|
| Copy
|
||||||
| Rand
|
| Rand
|
||||||
|
|
||||||
type t = risci list
|
type t = {
|
||||||
|
code : risci list;
|
||||||
|
inputval: int option
|
||||||
|
}
|
||||||
|
|
||||||
|
val pp_risci : out_channel -> risci -> unit
|
||||||
val pp : out_channel -> t -> unit
|
val pp : out_channel -> t -> unit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
177
lib/miniImp/RISCSemantics.ml
Normal file
177
lib/miniImp/RISCSemantics.ml
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
module Register = struct
|
||||||
|
type t = {index: string}
|
||||||
|
|
||||||
|
let compare a b = compare a.index b.index
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
module CodeMap = Map.Make(String)
|
||||||
|
module RegisterMap = Map.Make(Register)
|
||||||
|
module MemoryMap = Map.Make(Int)
|
||||||
|
|
||||||
|
module RISCArchitecture = struct
|
||||||
|
type t = {
|
||||||
|
code: RISC.RISCAssembly.risci list CodeMap.t;
|
||||||
|
registers: int RegisterMap.t;
|
||||||
|
memory: int MemoryMap.t
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let convert (prg: RISC.RISCAssembly.t) : RISC.RISCAssembly.risci list CodeMap.t =
|
||||||
|
let rec helper
|
||||||
|
(prg: RISC.RISCAssembly.risci list)
|
||||||
|
(current: RISC.RISCAssembly.risci list)
|
||||||
|
(current_label: string)
|
||||||
|
(map: RISC.RISCAssembly.risci list CodeMap.t)
|
||||||
|
: (RISC.RISCAssembly.risci list CodeMap.t) =
|
||||||
|
match prg with
|
||||||
|
| [] -> (CodeMap.union
|
||||||
|
(fun _ _ _ -> failwith "Two labels are the same")
|
||||||
|
(CodeMap.singleton current_label current)
|
||||||
|
map)
|
||||||
|
| Label l :: tl -> helper tl ([]) l
|
||||||
|
(CodeMap.union
|
||||||
|
(fun _ _ _ -> failwith "Two labels are the same")
|
||||||
|
(CodeMap.singleton current_label current)
|
||||||
|
map)
|
||||||
|
| instr :: tl -> helper tl (current @ [instr]) current_label map
|
||||||
|
in
|
||||||
|
match prg.code with
|
||||||
|
| Label "main" :: tl -> helper tl [] "main" CodeMap.empty
|
||||||
|
| _ -> failwith "Program should begind with label main"
|
||||||
|
|
||||||
|
let label_order (prg: RISC.RISCAssembly.t) : string list =
|
||||||
|
let rec helper
|
||||||
|
(prg: RISC.RISCAssembly.risci list)
|
||||||
|
: string list =
|
||||||
|
match prg with
|
||||||
|
[] -> []
|
||||||
|
| Label l :: tl -> l :: (helper tl)
|
||||||
|
| _ :: tl -> (helper tl)
|
||||||
|
in
|
||||||
|
helper (prg.code)
|
||||||
|
|
||||||
|
let reduce_instructions (prg: RISCArchitecture.t) (lo: string list) : int =
|
||||||
|
let match_operator_r (brop: RISC.RISCAssembly.brop) =
|
||||||
|
match brop with
|
||||||
|
| Add -> (+)
|
||||||
|
| Sub -> (-)
|
||||||
|
| Mult -> ( * )
|
||||||
|
| Div -> (/)
|
||||||
|
| Mod -> (mod)
|
||||||
|
| Pow -> (Utility.pow)
|
||||||
|
| And -> (Utility.int_and)
|
||||||
|
| Or -> (Utility.int_or)
|
||||||
|
| Eq -> (Utility.int_eq)
|
||||||
|
| Less -> (Utility.int_less)
|
||||||
|
| LessEq -> (Utility.int_less_eq)
|
||||||
|
| More -> (Utility.int_more)
|
||||||
|
| MoreEq -> (Utility.int_more_eq)
|
||||||
|
in
|
||||||
|
let match_operator_i (biop: RISC.RISCAssembly.biop) =
|
||||||
|
match biop with
|
||||||
|
| AddI -> (+)
|
||||||
|
| SubI -> (-)
|
||||||
|
| MultI -> ( * )
|
||||||
|
| DivI -> (/)
|
||||||
|
| ModI -> (mod)
|
||||||
|
| PowI -> (Utility.pow)
|
||||||
|
| AndI -> (Utility.int_and)
|
||||||
|
| OrI -> (Utility.int_or)
|
||||||
|
| EqI -> (Utility.int_eq)
|
||||||
|
| LessI -> (Utility.int_less)
|
||||||
|
| LessEqI -> (Utility.int_less_eq)
|
||||||
|
| MoreI -> (Utility.int_more)
|
||||||
|
| MoreEqI -> (Utility.int_more_eq)
|
||||||
|
in
|
||||||
|
|
||||||
|
let rec helper
|
||||||
|
(prg: RISCArchitecture.t)
|
||||||
|
(current: RISC.RISCAssembly.risci list)
|
||||||
|
(current_label: string)
|
||||||
|
: RISCArchitecture.t =
|
||||||
|
match current with
|
||||||
|
| [] -> (
|
||||||
|
(* falls to the next label *)
|
||||||
|
match List.find_index ((=) current_label) lo with
|
||||||
|
None -> prg (* should never happen *)
|
||||||
|
| Some i ->
|
||||||
|
if i + 1 < (List.length lo) then
|
||||||
|
helper prg (CodeMap.find (List.nth lo (i+1)) prg.code) (List.nth lo (i+1))
|
||||||
|
else
|
||||||
|
prg
|
||||||
|
)
|
||||||
|
| Nop :: tl -> helper prg tl current_label
|
||||||
|
| BRegOp (brop, r1, r2, r3) :: tl -> (
|
||||||
|
let n = (match_operator_r brop)
|
||||||
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
|
(RegisterMap.find {index = r2.index} prg.registers)
|
||||||
|
in
|
||||||
|
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
||||||
|
)
|
||||||
|
| BImmOp (biop, r1, i, r3) :: tl -> (
|
||||||
|
let n = (match_operator_i biop)
|
||||||
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
|
i
|
||||||
|
in
|
||||||
|
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
||||||
|
)
|
||||||
|
| URegOp (urop, r1, r3) :: tl -> (
|
||||||
|
match urop with
|
||||||
|
| Copy -> (
|
||||||
|
let n = RegisterMap.find {index = r1.index} prg.registers in
|
||||||
|
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
||||||
|
)
|
||||||
|
| Not -> (
|
||||||
|
let n = Utility.int_not
|
||||||
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
|
in
|
||||||
|
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
||||||
|
)
|
||||||
|
| Rand -> (
|
||||||
|
let n = Random.int
|
||||||
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
|
in
|
||||||
|
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| Load (r1, r3) :: tl -> (
|
||||||
|
let n = MemoryMap.find
|
||||||
|
(RegisterMap.find {index = r1.index} prg.registers)
|
||||||
|
prg.memory
|
||||||
|
in
|
||||||
|
helper {prg with registers = RegisterMap.add {index = r3.index} n prg.registers} tl current_label
|
||||||
|
)
|
||||||
|
| LoadI (r1, i) :: tl -> (
|
||||||
|
let n = i
|
||||||
|
in
|
||||||
|
helper {prg with registers = RegisterMap.add {index = r1.index} n prg.registers} tl current_label
|
||||||
|
)
|
||||||
|
| Store (r1, r3) :: tl -> (
|
||||||
|
let n = RegisterMap.find {index = r1.index} prg.registers in
|
||||||
|
let n1 = RegisterMap.find {index = r3.index} prg.registers in
|
||||||
|
helper {prg with memory = MemoryMap.add n1 n prg.memory} tl current_label
|
||||||
|
)
|
||||||
|
| Jump l :: _ -> helper prg (CodeMap.find l prg.code) l
|
||||||
|
| CJump (r, l1, l2) :: _ -> (
|
||||||
|
let br = (RegisterMap.find {index = r.index} prg.registers) > 0 in
|
||||||
|
if br
|
||||||
|
then
|
||||||
|
helper prg (CodeMap.find l1 prg.code) l1
|
||||||
|
else
|
||||||
|
helper prg (CodeMap.find l2 prg.code) l2
|
||||||
|
)
|
||||||
|
| Label _ :: tl -> helper prg tl current_label
|
||||||
|
in
|
||||||
|
RegisterMap.find
|
||||||
|
{index = "out"}
|
||||||
|
(helper prg (CodeMap.find "main" prg.code) "main").registers
|
||||||
|
|
||||||
|
|
||||||
|
let reduce (prg: RISC.RISCAssembly.t) : int =
|
||||||
|
reduce_instructions {code = convert prg;
|
||||||
|
registers =
|
||||||
|
RegisterMap.singleton
|
||||||
|
{index = "in"}
|
||||||
|
(Option.value prg.inputval ~default:0);
|
||||||
|
memory = MemoryMap.empty} (label_order prg)
|
||||||
5
lib/miniImp/RISCSemantics.mli
Normal file
5
lib/miniImp/RISCSemantics.mli
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module RISCArchitecture : sig
|
||||||
|
type t
|
||||||
|
end
|
||||||
|
|
||||||
|
val reduce : RISC.RISCAssembly.t -> int
|
||||||
@ -31,6 +31,42 @@ and a_exp =
|
|||||||
| PowerMod of a_exp * a_exp * a_exp (* a ^ a % a *)
|
| PowerMod of a_exp * a_exp * a_exp (* a ^ a % a *)
|
||||||
| Rand of a_exp (* rand(0, a) *)
|
| Rand of a_exp (* rand(0, a) *)
|
||||||
|
|
||||||
|
let pp_p_exp (ppf: Format.formatter) (p: p_exp) : unit =
|
||||||
|
let rec helper_c (ppf) (c: c_exp) : unit =
|
||||||
|
match c with
|
||||||
|
Skip -> Format.fprintf ppf "Skip"
|
||||||
|
| Assignment (x, a) -> Format.fprintf ppf "%S := @[<h>%a@]" x helper_a a
|
||||||
|
| Sequence (c1, c2) -> Format.fprintf ppf "@[<hv>Sequence (@;<1 2>%a,@;<1 0>%a@;<0 0>)@]" helper_c c1 helper_c c2
|
||||||
|
| If (b, c1, c2) -> Format.fprintf ppf "@[<hv>If @[<h>%a@]@;<1 2>then (@[<hv>%a@])@;<1 2>else (@[<hv>%a@])@]" helper_b b helper_c c1 helper_c c2
|
||||||
|
| While (b, c) -> Format.fprintf ppf "@[<hv>While @[<h>%a@] do@;<1 2>%a@]@;<0 0>" helper_b b helper_c c
|
||||||
|
| For (c1, b, c2, c3) -> Format.fprintf ppf "@[<h>For (@;<0 2>%a,@;<1 2>@[<h>%a@],@;<1 2>%a) do@]@;<1 4>%a@;<0 0>" helper_c c1 helper_b b helper_c c2 helper_c c3
|
||||||
|
and helper_b (ppf) (b: b_exp) =
|
||||||
|
match b with
|
||||||
|
Boolean (b) -> Format.fprintf ppf "%b" b
|
||||||
|
| BAnd (b1, b2) -> Format.fprintf ppf "(%a &&@;<1 2>%a)" helper_b b1 helper_b b2
|
||||||
|
| BOr (b1, b2) -> Format.fprintf ppf "(%a ||@;<1 2>%a)" helper_b b1 helper_b b2
|
||||||
|
| BNot (b) -> Format.fprintf ppf "(not %a)" helper_b b
|
||||||
|
| BCmp (a1, a2) -> Format.fprintf ppf "(%a ==@;<1 2>%a)" helper_a a1 helper_a a2
|
||||||
|
| BCmpLess (a1, a2) -> Format.fprintf ppf "(%a <@;<1 2>%a)" helper_a a1 helper_a a2
|
||||||
|
| BCmpLessEq (a1, a2) -> Format.fprintf ppf "(%a <=@;<1 2>%a)" helper_a a1 helper_a a2
|
||||||
|
| BCmpGreater (a1, a2) -> Format.fprintf ppf "(%a >@;<1 2>%a)" helper_a a1 helper_a a2
|
||||||
|
| BCmpGreaterEq (a1, a2) -> Format.fprintf ppf "(%a >=@;<1 2>%a)" helper_a a1 helper_a a2
|
||||||
|
and helper_a (ppf) (a: a_exp) =
|
||||||
|
match a with
|
||||||
|
Variable v -> Format.fprintf ppf "%S" v
|
||||||
|
| Integer n -> Format.fprintf ppf "%i" n
|
||||||
|
| Plus (a1, a2) -> Format.fprintf ppf "%a +@;<1 2>%a" helper_a a1 helper_a a2
|
||||||
|
| Minus (a1, a2) -> Format.fprintf ppf "%a -@;<1 2>%a" helper_a a1 helper_a a2
|
||||||
|
| Times (a1, a2) -> Format.fprintf ppf "%a *@;<1 2>%a" helper_a a1 helper_a a2
|
||||||
|
| Division (a1, a2) -> Format.fprintf ppf "%a /@;<1 2>%a" helper_a a1 helper_a a2
|
||||||
|
| Modulo (a1, a2) -> Format.fprintf ppf "%a %%@;<1 2>%a" helper_a a1 helper_a a2
|
||||||
|
| Power (a1, a2) -> Format.fprintf ppf "(%a ^@;<1 2>%a)" helper_a a1 helper_a a2
|
||||||
|
| PowerMod (a1, a2, a3) -> Format.fprintf ppf "(%a ^ %a %% %a)" helper_a a1 helper_a a2 helper_a a3
|
||||||
|
| Rand (a) -> Format.fprintf ppf "Rand (%a)" helper_a a
|
||||||
|
in
|
||||||
|
match p with
|
||||||
|
| Main (i, o, exp) ->
|
||||||
|
Format.fprintf ppf "def main with (input %S) (output %S) as @.%a" i o helper_c exp
|
||||||
|
|
||||||
module VariableMap = Map.Make(String)
|
module VariableMap = Map.Make(String)
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,7 @@ and a_exp =
|
|||||||
| PowerMod of a_exp * a_exp * a_exp (* a ^ a % a *)
|
| PowerMod of a_exp * a_exp * a_exp (* a ^ a % a *)
|
||||||
| Rand of a_exp (* rand(0, a) *)
|
| Rand of a_exp (* rand(0, a) *)
|
||||||
|
|
||||||
|
val pp_p_exp : Format.formatter -> p_exp -> unit
|
||||||
|
|
||||||
module VariableMap : Map.S with type key = variable
|
module VariableMap : Map.S with type key = variable
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,10 @@
|
|||||||
(library
|
(library
|
||||||
(name miniImp)
|
(name miniImp)
|
||||||
(public_name miniImp)
|
(public_name miniImp)
|
||||||
(modules Lexer Parser Types Semantics CfgImp CfgRISC RISC)
|
(modules Lexer Parser Types Semantics
|
||||||
|
CfgImp ReplacePowerMod
|
||||||
|
CfgRISC
|
||||||
|
RISC RISCSemantics)
|
||||||
(libraries cfg utility menhirLib))
|
(libraries cfg utility menhirLib))
|
||||||
|
|
||||||
(include_subdirs qualified)
|
(include_subdirs qualified)
|
||||||
|
|||||||
246
lib/miniImp/replacePowerMod.ml
Normal file
246
lib/miniImp/replacePowerMod.ml
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
let rewrite_instructions (prg: Types.p_exp) : Types.p_exp =
|
||||||
|
(* function takes a program and replaces all occurrences of powermod with
|
||||||
|
simpler instructions *)
|
||||||
|
let i, o, prg = (
|
||||||
|
match prg with
|
||||||
|
| Main (i, o, exp) -> i, o, exp
|
||||||
|
) in
|
||||||
|
|
||||||
|
let rec contains_rewrite (prg: Types.c_exp) : Types.a_exp option =
|
||||||
|
(* if the ast contains powermod anywhere returns the powermod, otherwise
|
||||||
|
returns none *)
|
||||||
|
match prg with
|
||||||
|
| Skip -> None
|
||||||
|
| Assignment (_, a) -> contains_rewrite_a a
|
||||||
|
| Sequence (c1, c2) -> (
|
||||||
|
match contains_rewrite c1, contains_rewrite c2 with
|
||||||
|
| None, None -> None
|
||||||
|
| Some a, _
|
||||||
|
| _, Some a -> Some a
|
||||||
|
)
|
||||||
|
| If (b, c1, c2) -> (
|
||||||
|
match contains_rewrite_b b, contains_rewrite c1, contains_rewrite c2 with
|
||||||
|
| None, None, None -> None
|
||||||
|
| Some a, _, _
|
||||||
|
| _, Some a, _
|
||||||
|
| _, _, Some a -> Some a
|
||||||
|
)
|
||||||
|
| While (b, c) -> (
|
||||||
|
match contains_rewrite_b b, contains_rewrite c with
|
||||||
|
| None, None -> None
|
||||||
|
| Some a, _
|
||||||
|
| _, Some a -> Some a
|
||||||
|
)
|
||||||
|
| For (c1, b, c2, c3) -> (
|
||||||
|
match contains_rewrite c1, contains_rewrite_b b, contains_rewrite c2, contains_rewrite c3 with
|
||||||
|
| None, None, None, None -> None
|
||||||
|
| Some a, _, _, _
|
||||||
|
| _, Some a, _, _
|
||||||
|
| _, _, Some a, _
|
||||||
|
| _, _, _, Some a -> Some a
|
||||||
|
)
|
||||||
|
and contains_rewrite_b (b: Types.b_exp) : Types.a_exp option =
|
||||||
|
match b with
|
||||||
|
| Boolean (_) -> None
|
||||||
|
| BAnd (b1, b2)
|
||||||
|
| BOr (b1, b2) -> (
|
||||||
|
match contains_rewrite_b b1, contains_rewrite_b b2 with
|
||||||
|
None, None -> None
|
||||||
|
| Some a, _
|
||||||
|
| _, Some a -> Some a
|
||||||
|
)
|
||||||
|
| BNot (b) -> contains_rewrite_b b
|
||||||
|
| BCmp (a1, a2)
|
||||||
|
| BCmpLess (a1, a2)
|
||||||
|
| BCmpLessEq (a1, a2)
|
||||||
|
| BCmpGreater (a1, a2)
|
||||||
|
| BCmpGreaterEq (a1, a2) -> (
|
||||||
|
match contains_rewrite_a a1, contains_rewrite_a a2 with
|
||||||
|
None, None -> None
|
||||||
|
| Some a, _
|
||||||
|
| _, Some a -> Some a
|
||||||
|
)
|
||||||
|
and contains_rewrite_a (a: Types.a_exp) : Types.a_exp option =
|
||||||
|
match a with
|
||||||
|
| Variable _
|
||||||
|
| Integer _ -> None
|
||||||
|
| Plus (a1, a2)
|
||||||
|
| Minus (a1, a2)
|
||||||
|
| Times (a1, a2)
|
||||||
|
| Division (a1, a2)
|
||||||
|
| Modulo (a1, a2)
|
||||||
|
| Power (a1, a2) -> (
|
||||||
|
match contains_rewrite_a a1, contains_rewrite_a a2 with
|
||||||
|
None, None -> None
|
||||||
|
| Some a, _
|
||||||
|
| _, Some a -> Some a
|
||||||
|
)
|
||||||
|
| PowerMod (_) -> Some a
|
||||||
|
| Rand (a) -> contains_rewrite_a a
|
||||||
|
in
|
||||||
|
|
||||||
|
(* obtain the list of used variables so that fresh ones can be created *)
|
||||||
|
let rec uv (prg: Types.c_exp) : Types.variable list =
|
||||||
|
match prg with
|
||||||
|
| Skip -> []
|
||||||
|
| Assignment (x, _) -> [x]
|
||||||
|
| Sequence (c1, c2) -> uv c1 @ uv c2
|
||||||
|
| If (_, c1, c2) -> uv c1 @ uv c2
|
||||||
|
| While (_, c) -> uv c
|
||||||
|
| For (c1, _, c2, c3) -> uv c1 @ uv c2 @ uv c3
|
||||||
|
in
|
||||||
|
let usedvariables = i :: o :: (uv prg) in
|
||||||
|
|
||||||
|
let counter = ref 0 in
|
||||||
|
let new_fresh_var (pref: string) : Types.variable =
|
||||||
|
let rec h () =
|
||||||
|
let candidate = pref ^ (string_of_int !counter) in
|
||||||
|
if (List.mem candidate usedvariables) then (
|
||||||
|
counter := !counter + 1;
|
||||||
|
h ()
|
||||||
|
) else (
|
||||||
|
counter := !counter + 1;
|
||||||
|
candidate
|
||||||
|
)
|
||||||
|
in
|
||||||
|
h ()
|
||||||
|
in
|
||||||
|
|
||||||
|
(* functions that replace a pattern in a subexpression *)
|
||||||
|
let rec replace_occurrence_a (pattern: Types.a_exp) (replace: Types.a_exp) (a: Types.a_exp) : Types.a_exp =
|
||||||
|
if a = pattern then
|
||||||
|
replace
|
||||||
|
else (
|
||||||
|
let r_o_a = replace_occurrence_a pattern replace in
|
||||||
|
match a with
|
||||||
|
| Variable _
|
||||||
|
| Integer _ -> a
|
||||||
|
| Plus (a1, a2) -> Plus (r_o_a a1, r_o_a a2)
|
||||||
|
| Minus (a1, a2) -> Minus (r_o_a a1, r_o_a a2)
|
||||||
|
| Times (a1, a2) -> Times (r_o_a a1, r_o_a a2)
|
||||||
|
| Division (a1, a2) -> Division (r_o_a a1, r_o_a a2)
|
||||||
|
| Modulo (a1, a2) -> Modulo (r_o_a a1, r_o_a a2)
|
||||||
|
| Power (a1, a2) -> Power (r_o_a a1, r_o_a a2)
|
||||||
|
| PowerMod (a1, a2, a3) -> PowerMod (r_o_a a1, r_o_a a2, r_o_a a3)
|
||||||
|
| Rand (a) -> Rand (r_o_a a)
|
||||||
|
)
|
||||||
|
and replace_occurrence_b (pattern: Types.a_exp) (replace: Types.a_exp) (b: Types.b_exp) : Types.b_exp =
|
||||||
|
let r_o_b = replace_occurrence_b pattern replace in
|
||||||
|
let r_o_a = replace_occurrence_a pattern replace in
|
||||||
|
match b with
|
||||||
|
| Boolean _ -> b
|
||||||
|
| BAnd (b1, b2) -> BAnd (r_o_b b1, r_o_b b2)
|
||||||
|
| BOr (b1, b2) -> BOr (r_o_b b1, r_o_b b2)
|
||||||
|
| BNot (b) -> BNot (r_o_b b)
|
||||||
|
| BCmp (a1, a2) -> BCmp (r_o_a a1, r_o_a a2)
|
||||||
|
| BCmpLess (a1, a2) -> BCmpLess (r_o_a a1, r_o_a a2)
|
||||||
|
| BCmpLessEq (a1, a2) -> BCmpLessEq (r_o_a a1, r_o_a a2)
|
||||||
|
| BCmpGreater (a1, a2) -> BCmpGreater (r_o_a a1, r_o_a a2)
|
||||||
|
| BCmpGreaterEq (a1, a2) -> BCmpGreaterEq (r_o_a a1, r_o_a a2)
|
||||||
|
in
|
||||||
|
|
||||||
|
(* function that creates the equivalent code for a powermod using simpler
|
||||||
|
instructions *)
|
||||||
|
let partial freshres a1 a2 a3 : Types.c_exp =
|
||||||
|
let freshpow = new_fresh_var "pow" in
|
||||||
|
let freshexp = new_fresh_var "exp" in
|
||||||
|
let freshmod = new_fresh_var "mod" in
|
||||||
|
Sequence (
|
||||||
|
Sequence (
|
||||||
|
Sequence (
|
||||||
|
Assignment (freshpow, a1),
|
||||||
|
Assignment (freshexp, a2)),
|
||||||
|
Sequence (
|
||||||
|
Assignment (freshmod, a3),
|
||||||
|
Assignment (freshres, Integer 1))),
|
||||||
|
Sequence (
|
||||||
|
If (BCmpLess (Variable freshexp, Integer 0),
|
||||||
|
Assignment (freshexp, Minus (Integer 0, Variable freshexp)),
|
||||||
|
Skip),
|
||||||
|
While (
|
||||||
|
BCmpGreater (Variable freshexp, Integer 0),
|
||||||
|
Sequence (
|
||||||
|
If (BCmp (Integer 1, Modulo (Variable freshexp, Integer 2)),
|
||||||
|
Assignment (freshres,
|
||||||
|
Modulo (Times (Variable freshres,
|
||||||
|
Variable freshpow),
|
||||||
|
Variable freshmod)),
|
||||||
|
Skip),
|
||||||
|
Sequence (
|
||||||
|
Assignment (freshpow,
|
||||||
|
Modulo (Times (Variable freshpow,
|
||||||
|
Variable freshpow),
|
||||||
|
Variable freshmod)),
|
||||||
|
Assignment (freshexp, Division (Variable freshexp, Integer 2))
|
||||||
|
)))))
|
||||||
|
in
|
||||||
|
|
||||||
|
let replace_pwm (pwm: Types.a_exp) (p: Types.c_exp) : Types.c_exp =
|
||||||
|
match pwm, p with
|
||||||
|
| PowerMod (a1, a2, a3), Assignment (x, a) ->
|
||||||
|
let freshres = new_fresh_var "res" in
|
||||||
|
Sequence (
|
||||||
|
partial freshres a1 a2 a3,
|
||||||
|
Assignment(x, replace_occurrence_a pwm (Variable freshres) a)
|
||||||
|
)
|
||||||
|
| PowerMod (a1, a2, a3), If (b, ifa1, ifa2) ->
|
||||||
|
let freshres = new_fresh_var "res" in
|
||||||
|
Sequence (
|
||||||
|
partial freshres a1 a2 a3,
|
||||||
|
If (replace_occurrence_b pwm (Variable freshres) b, ifa1, ifa2)
|
||||||
|
)
|
||||||
|
| PowerMod (a1, a2, a3), While (b, wa) ->
|
||||||
|
let freshres = new_fresh_var "res" in
|
||||||
|
Sequence (
|
||||||
|
partial freshres a1 a2 a3,
|
||||||
|
While (replace_occurrence_b pwm (Variable freshres) b, wa)
|
||||||
|
)
|
||||||
|
| PowerMod (a1, a2, a3), For (fora1, b, fora2, fora3) ->
|
||||||
|
let freshres = new_fresh_var "res" in
|
||||||
|
Sequence (
|
||||||
|
partial freshres a1 a2 a3,
|
||||||
|
For (fora1, replace_occurrence_b pwm (Variable freshres) b, fora2, fora3)
|
||||||
|
)
|
||||||
|
| _ -> failwith "PowerMod is not present"
|
||||||
|
in
|
||||||
|
|
||||||
|
let rec rw_a (prg: Types.c_exp) : Types.c_exp =
|
||||||
|
match prg with
|
||||||
|
| Skip -> Skip
|
||||||
|
| Assignment (x, a) -> (
|
||||||
|
match contains_rewrite_a a with
|
||||||
|
None -> Assignment (x, a)
|
||||||
|
| Some (PowerMod (a1, a2, a3)) -> (
|
||||||
|
replace_pwm (PowerMod (a1, a2, a3)) prg
|
||||||
|
)
|
||||||
|
| Some _ -> failwith "Found powmod then lost it."
|
||||||
|
)
|
||||||
|
| Sequence (c1, c2) -> Sequence (rw_a c1, rw_a c2)
|
||||||
|
| If (b, c1, c2) -> (
|
||||||
|
match contains_rewrite_b b with
|
||||||
|
None -> If (b, rw_a c1, rw_a c2)
|
||||||
|
| Some (PowerMod (a1, a2, a3)) ->
|
||||||
|
replace_pwm (PowerMod (a1, a2, a3)) prg
|
||||||
|
| Some _ -> failwith "Found powmod then lost it."
|
||||||
|
)
|
||||||
|
| While (b, c) -> (
|
||||||
|
match contains_rewrite_b b with
|
||||||
|
None -> While (b, rw_a c)
|
||||||
|
| Some (PowerMod (a1, a2, a3)) ->
|
||||||
|
replace_pwm (PowerMod (a1, a2, a3)) prg
|
||||||
|
| Some _ -> failwith "Found powmod then lost it."
|
||||||
|
)
|
||||||
|
| For (c1, b, c2, c3) -> (
|
||||||
|
match contains_rewrite_b b with
|
||||||
|
None -> For (rw_a c1, b, rw_a c2, rw_a c3)
|
||||||
|
| Some (PowerMod (a1, a2, a3)) ->
|
||||||
|
replace_pwm (PowerMod (a1, a2, a3)) prg
|
||||||
|
| Some _ -> failwith "Found powmod then lost it."
|
||||||
|
)
|
||||||
|
in
|
||||||
|
|
||||||
|
(* we first check that at least one powermod is present *)
|
||||||
|
if Option.is_none (contains_rewrite prg) then
|
||||||
|
Main (i, o, prg)
|
||||||
|
else
|
||||||
|
Main (i, o, rw_a prg)
|
||||||
1
lib/miniImp/replacePowerMod.mli
Normal file
1
lib/miniImp/replacePowerMod.mli
Normal file
@ -0,0 +1 @@
|
|||||||
|
val rewrite_instructions : Types.p_exp -> Types.p_exp
|
||||||
@ -12,6 +12,34 @@ let rec powmod a d = function
|
|||||||
let b = (powmod a d (n / 2)) mod d in
|
let b = (powmod a d (n / 2)) mod d in
|
||||||
(((b * b) mod d) * (if n mod 2 = 0 then 1 else a)) mod d
|
(((b * b) mod d) * (if n mod 2 = 0 then 1 else a)) mod d
|
||||||
|
|
||||||
|
let int_and a b =
|
||||||
|
match (a>0, b>0) with
|
||||||
|
true, true -> 1
|
||||||
|
| _, _ -> 0
|
||||||
|
|
||||||
|
let int_or a b =
|
||||||
|
match (a>0, b>0) with
|
||||||
|
false, false -> 0
|
||||||
|
| _, _ -> 1
|
||||||
|
|
||||||
|
let int_eq a b =
|
||||||
|
if a = b then 1 else 0
|
||||||
|
|
||||||
|
let int_less a b =
|
||||||
|
if a < b then 1 else 0
|
||||||
|
|
||||||
|
let int_less_eq a b =
|
||||||
|
if a <= b then 1 else 0
|
||||||
|
|
||||||
|
let int_more a b =
|
||||||
|
if a > b then 1 else 0
|
||||||
|
|
||||||
|
let int_more_eq a b =
|
||||||
|
if a >= b then 1 else 0
|
||||||
|
|
||||||
|
let int_not a =
|
||||||
|
if a > 0 then 0 else 1
|
||||||
|
|
||||||
let rec fromIntToString (alphabet: string) (x: int) : string =
|
let rec fromIntToString (alphabet: string) (x: int) : string =
|
||||||
let base = String.length alphabet in
|
let base = String.length alphabet in
|
||||||
if x < 0 then
|
if x < 0 then
|
||||||
|
|||||||
@ -2,4 +2,13 @@ val pow : int -> int -> int
|
|||||||
|
|
||||||
val powmod : int -> int -> int -> int
|
val powmod : int -> int -> int -> int
|
||||||
|
|
||||||
|
val int_and : int -> int -> int
|
||||||
|
val int_or : int -> int -> int
|
||||||
|
val int_eq : int -> int -> int
|
||||||
|
val int_less : int -> int -> int
|
||||||
|
val int_less_eq : int -> int -> int
|
||||||
|
val int_more : int -> int -> int
|
||||||
|
val int_more_eq : int -> int -> int
|
||||||
|
val int_not : int -> int
|
||||||
|
|
||||||
val fromIntToString : string -> int -> string
|
val fromIntToString : string -> int -> string
|
||||||
|
|||||||
@ -6,6 +6,10 @@
|
|||||||
(name testingImpParser)
|
(name testingImpParser)
|
||||||
(libraries miniImp))
|
(libraries miniImp))
|
||||||
|
|
||||||
|
(test
|
||||||
|
(name testingRISC)
|
||||||
|
(libraries miniImp))
|
||||||
|
|
||||||
(test
|
(test
|
||||||
(name testingFun)
|
(name testingFun)
|
||||||
(libraries miniFun))
|
(libraries miniFun))
|
||||||
@ -16,4 +20,4 @@
|
|||||||
|
|
||||||
(test
|
(test
|
||||||
(name testingTypeFunParser)
|
(name testingTypeFunParser)
|
||||||
(libraries miniFun))
|
(libraries miniFun))
|
||||||
|
|||||||
8
test/testingRISC.expected
Normal file
8
test/testingRISC.expected
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Identity program: 1
|
||||||
|
Factorial program: 3628800
|
||||||
|
Hailstone sequence's lenght program: 351
|
||||||
|
Sum multiples of 3 and 5 program: 35565945
|
||||||
|
Rand program: true
|
||||||
|
Fibonacci program: 4807526976
|
||||||
|
Miller-Rabin primality test program 1: 0
|
||||||
|
Miller-Rabin primality test program 2: 1
|
||||||
128
test/testingRISC.ml
Normal file
128
test/testingRISC.ml
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
open MiniImp
|
||||||
|
|
||||||
|
let compute x i =
|
||||||
|
Lexing.from_string x |>
|
||||||
|
Parser.prg Lexer.lex |>
|
||||||
|
CfgImp.convert_io i |>
|
||||||
|
CfgRISC.convert |>
|
||||||
|
RISC.convert |>
|
||||||
|
RISCSemantics.reduce
|
||||||
|
|
||||||
|
|
||||||
|
(* -------------------------------------------------------------------------- *)
|
||||||
|
(* Identity program *)
|
||||||
|
let program =
|
||||||
|
"def main with input a output b as b := a"
|
||||||
|
;;
|
||||||
|
|
||||||
|
Printf.printf "Identity program: ";
|
||||||
|
Printf.printf "%d\n" (compute program 1)
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* -------------------------------------------------------------------------- *)
|
||||||
|
(* Factorial program *)
|
||||||
|
let program =
|
||||||
|
"def main with input a output b as
|
||||||
|
b := 1;
|
||||||
|
for (i := 1, i <= a, i := i + 1) do
|
||||||
|
b := b * i;
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
Printf.printf "Factorial program: ";
|
||||||
|
Printf.printf "%d\n" (compute program 10)
|
||||||
|
|
||||||
|
(* -------------------------------------------------------------------------- *)
|
||||||
|
(* Hailstone sequence's lenght program *)
|
||||||
|
let program =
|
||||||
|
"def main with input a output b as
|
||||||
|
b := 1;
|
||||||
|
while not a == 1 do (
|
||||||
|
b := b + 1;
|
||||||
|
if ((a % 2) == 1) then a := 3 * a + 1 else a := a / 2
|
||||||
|
)
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
Printf.printf "Hailstone sequence's lenght program: ";
|
||||||
|
Printf.printf "%d\n" (compute program 77031)
|
||||||
|
|
||||||
|
(* -------------------------------------------------------------------------- *)
|
||||||
|
(* Sum multiples of 3 and 5 program *)
|
||||||
|
let program =
|
||||||
|
"def main with input a output b as
|
||||||
|
b := 0;
|
||||||
|
for (i := 0, i <= a, i := i+1) do
|
||||||
|
if (i % 3 == 0 || i % 5 == 0) then b := b + i;
|
||||||
|
else skip;
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
Printf.printf "Sum multiples of 3 and 5 program: ";
|
||||||
|
Printf.printf "%d\n" (compute program 12345)
|
||||||
|
|
||||||
|
(* -------------------------------------------------------------------------- *)
|
||||||
|
(* Rand program *)
|
||||||
|
let program =
|
||||||
|
"def main with input a output b as b := rand(a)"
|
||||||
|
;;
|
||||||
|
|
||||||
|
Printf.printf "Rand program: ";
|
||||||
|
Printf.printf "%b\n" ((compute program 10) < 10)
|
||||||
|
|
||||||
|
(* -------------------------------------------------------------------------- *)
|
||||||
|
(* Fibonacci program *)
|
||||||
|
let program =
|
||||||
|
"def main with input n output fnext as
|
||||||
|
fnow := 0;
|
||||||
|
fnext := 1;
|
||||||
|
while (n > 1) do (
|
||||||
|
tmp := fnow + fnext;
|
||||||
|
fnow := fnext;
|
||||||
|
fnext := tmp;
|
||||||
|
n := n - 1;
|
||||||
|
)
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
Printf.printf "Fibonacci program: ";
|
||||||
|
Printf.printf "%d\n" (compute program 48)
|
||||||
|
|
||||||
|
(* -------------------------------------------------------------------------- *)
|
||||||
|
(* Miller-Rabin primality test program *)
|
||||||
|
let program =
|
||||||
|
"def main with input n output result as
|
||||||
|
if (n % 2) == 0 then result := 1
|
||||||
|
else (
|
||||||
|
|
||||||
|
result := 0;
|
||||||
|
s := 0;
|
||||||
|
while (0 == ((n - 1) / (2 ^ s)) % 2) do (
|
||||||
|
s := s + 1
|
||||||
|
);
|
||||||
|
d := ((n - 1) / 2 ^ s);
|
||||||
|
for (i := 20, i > 0, i := i - 1) do (
|
||||||
|
a := rand(n - 4) + 2;
|
||||||
|
x := powmod(a, d, n);
|
||||||
|
for (j := 0, j < s, j := j+1) do (
|
||||||
|
y := powmod(x, 2, n);
|
||||||
|
if (y == 1 && (not x == 1) && (not x == n - 1)) then
|
||||||
|
result := 1;
|
||||||
|
else
|
||||||
|
skip;
|
||||||
|
x := y;
|
||||||
|
);
|
||||||
|
if not y == 1 then result := 1;
|
||||||
|
else skip;
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* should return 0 because prime *)
|
||||||
|
Printf.printf "Miller-Rabin primality test program 1: ";
|
||||||
|
Printf.printf "%d\n" (compute program 179424673);
|
||||||
|
|
||||||
|
(* should return 1 because not prime *)
|
||||||
|
Printf.printf "Miller-Rabin primality test program 2: ";
|
||||||
|
Printf.printf "%d\n" (compute program 179424675);
|
||||||
Reference in New Issue
Block a user