open Printf
open Print
open MIPSOps
open Primitive
open PP
let rec typ () = function
| TypInt ->
sprintf "integer"
| TypBool ->
sprintf "boolean"
| TypArray t ->
sprintf "array of %a" typ t
let constant () = function
| ConstBool true ->
sprintf "true"
| ConstBool false ->
sprintf "false"
| ConstInt i ->
sprintf "%ld" i
let binop = function
| OpAdd ->
"+"
| OpSub ->
"-"
| OpMul ->
"*"
| OpDiv ->
"/"
| OpLt ->
"<"
| OpLe ->
"<="
| OpGt ->
">"
| OpGe ->
">="
| OpEq ->
"="
| OpNe ->
"<>"
let rec expr0 () = function
| EConst c ->
sprintf "%a" constant c
| EGetVar x ->
sprintf "%s" x
| EFunCall (c, es) ->
sprintf "%s(%a)" (PrintPrimitive.callee c) (seplist comma expr) es
| EArrayAlloc (t, e) ->
sprintf "new array of %a [%a]" typ t expr e
| e ->
sprintf "(%a)" expr e
and expr1 () = function
| EArrayGet (ea, ei) ->
sprintf "%a[%a]" expr1 ea expr ei
| e ->
expr0 () e
and expr2 () = function
| EUnOp (UOpNeg, e) ->
sprintf "-%a" expr1 e
| e ->
expr1 () e
and expr3 () = function
| EBinOp ((OpMul | OpDiv) as op, e1, e2) ->
sprintf "%a %s %a" expr3 e1 (binop op) expr2 e2
| e ->
expr2 () e
and expr4 () = function
| EBinOp ((OpSub | OpAdd) as op, e1, e2) ->
sprintf "%a %s %a" expr4 e1 (binop op) expr3 e2
| e ->
expr3 () e
and expr5 () = function
| EBinOp ((OpLt | OpLe | OpGt | OpGe | OpEq | OpNe) as op, e1, e2) ->
sprintf "%a %s %a" expr4 e1 (binop op) expr4 e2
| e ->
expr4 () e
and expr () e =
expr5 () e
let rec cond0 () = function
| CExpression e ->
expr () e
| CNot c ->
sprintf "not %a" cond0 c
| c ->
sprintf "(%a)" cond c
and cond1 () = function
| CAnd (c1, c2) ->
sprintf "%a and %a" cond1 c1 cond0 c2
| c ->
cond0 () c
and cond2 () = function
| COr (c1, c2) ->
sprintf "%a or %a" cond2 c1 cond1 c2
| c ->
cond1 () c
and cond () c =
cond2 () c
let mkblock contents () c =
sprintf "begin%a%tend" (indent 2 contents) c nl
let rec instr () = function
| IProcCall (c, es) ->
sprintf "%s(%a)" (PrintPrimitive.callee c) (seplist comma expr) es
| ISetVar (x, e) ->
sprintf "%s := %a" x expr e
| IArraySet (ea, ei, ev) ->
sprintf "%a[%a] := %a" expr1 ea expr ei expr ev
| IIf (c, i1, i2) ->
sprintf "if %a then%a%telse%a"
cond c
(indent 2 instr) i1
nl
(indent 2 instr) i2
| IWhile (c, i) ->
sprintf "while %a do%a"
cond c
(indent 2 instr) i
| ISeq is ->
sprintf "%a" (mkblock (seplist seminl instr)) is
and block () i =
match i with
| ISeq _ ->
instr () i
| i ->
sprintf "%a" (mkblock instr) i
let binding () (x, t) =
sprintf "%s : %a" x typ t
let vars () vars =
annlist var (indent 2 (termlist seminl binding)) () vars
let proc () (name, proc) =
Settings.delimit name (
match proc.result with
| None ->
sprintf "procedure %s(%a);\n%a%a;"
name
(seplist semicolon binding) proc.formals
vars (StringMap.to_association_list proc.locals)
block proc.body
| Some t ->
sprintf "function %s(%a) : %a;\n%a%a;"
name
(seplist semicolon binding) proc.formals
typ t
vars (StringMap.to_association_list proc.locals)
block proc.body
)
let print_program () p =
sprintf "program\n\n%a\n%a%a.\n"
vars (StringMap.to_association_list p.globals)
(termlist nlnl proc) (StringMap.to_association_list p.defs)
block p.main