2022-12-10 17:51:31 +01:00
open Ast
2022-12-13 14:50:18 +01:00
open Baselib
2022-12-10 17:51:31 +01:00
let collect_constant_strings code =
2022-12-27 17:07:24 +01:00
let counter = ref 0 in
2022-12-13 14:50:18 +01:00
let env = ref Env . empty in
2022-12-10 17:51:31 +01:00
let ccs_value = function
| V1 . Void -> V2 . Void , []
| V1 . Bool b -> V2 . Bool b , []
| V1 . Int n -> V2 . Int n , []
2022-12-11 03:35:52 +01:00
| V1 . Str s ->
2022-12-13 14:50:18 +01:00
( match Env . find_opt s ! env with
| Some lbl -> V2 . Data lbl , [ lbl , Mips . Asciiz s ]
| None ->
let lbl = " str " ^ string_of_int ! counter in
env := Env . add s lbl ! env ;
2022-12-27 17:07:24 +01:00
incr counter ;
2022-12-13 14:50:18 +01:00
V2 . Data lbl , [ lbl , Mips . Asciiz s ] )
2022-12-10 17:51:31 +01:00
in
let rec ccs_expr = function
| IR1 . Val v ->
2022-12-13 16:09:25 +01:00
let v2 , ccs = ccs_value v in
IR2 . Val v2 , ccs
2022-12-10 17:51:31 +01:00
| IR1 . Var v -> IR2 . Var v , []
| IR1 . Call ( fn , args ) ->
2022-12-13 14:50:18 +01:00
let args2 = List . map ccs_expr args in
IR2 . Call ( fn , List . map fst args2 ) , List . flatten ( List . map snd args2 )
2022-12-10 17:51:31 +01:00
in
2022-12-13 16:09:25 +01:00
let rec ccs_instr = function
2022-12-10 17:51:31 +01:00
| IR1 . Decl v -> IR2 . Decl v , []
| IR1 . Assign ( lv , e ) ->
2022-12-13 16:09:25 +01:00
let e2 , ccs = ccs_expr e in
IR2 . Assign ( lv , e2 ) , ccs
2022-12-10 17:51:31 +01:00
| IR1 . Do e ->
2022-12-13 16:09:25 +01:00
let e2 , ccs = ccs_expr e in
IR2 . Do e2 , ccs
| IR1 . Cond ( e , ib , eb ) ->
let e2 , ccs = ccs_expr e in
let ib2 , ccs2 = ccs_block ib in
let eb2 , ccs3 = ccs_block eb in
IR2 . Cond ( e2 , ib2 , eb2 ) , List . flatten [ ccs ; ccs2 ; ccs3 ]
2022-12-13 17:10:14 +01:00
| IR1 . Loop ( e , b ) ->
let e2 , ccs = ccs_expr e in
let b2 , ccs2 = ccs_block b in
IR2 . Loop ( e2 , b2 ) , List . flatten [ ccs ; ccs2 ]
2022-12-10 17:51:31 +01:00
| IR1 . Return e ->
2022-12-13 16:09:25 +01:00
let e2 , ccs = ccs_expr e in
IR2 . Return e2 , ccs
and ccs_block = function
| [] -> [] , []
| i :: s ->
let i2 , ccs_i = ccs_instr i in
let b , ccs_r = ccs_block s in
i2 :: b , List . flatten [ ccs_i ; ccs_r ]
2022-12-10 17:51:31 +01:00
in
let ccs_def ( IR1 . Func ( name , args , body ) ) =
2022-12-13 16:09:25 +01:00
let body2 , ccs = ccs_block body in
IR2 . Func ( name , args , body2 ) , ccs
2022-12-10 17:51:31 +01:00
in
let code2 = List . map ccs_def code in
2022-12-13 14:50:18 +01:00
( List . map fst code2
, List . fold_left
( fun list el -> if List . mem el list then list else el :: list )
[]
( List . flatten ( List . map snd code2 ) ) )
2022-12-10 17:51:31 +01:00
;;
let simplify ir = collect_constant_strings ir