open Parser
open Ast
let indent level = String.make (level*2) ' '
let _id x = x
let pp_lit = function
| Int(i) -> Printf.sprintf "Int(%d)" i
| Float(f) -> Printf.sprintf "Float(%f)" f
| String(s) -> Printf.sprintf "String(%s)" s
| Bool(b) -> Printf.sprintf "Bool(%B)" b
let pp_arith = function
| Add -> "Add"
| Sub -> "Sub"
| Prod -> "Prod"
| Div -> "Div"
| Mod -> "Mod"
| Neg -> "Neg"
| Pow -> "Pow"
let pp_numtest = function
| Eq -> "Eq"
| Neq -> "Neq"
| Less -> "Less"
| Grtr -> "Grtr"
| Leq -> "Leq"
| Geq -> "Geq"
let pp_combtest = function
| And -> "And"
| Or -> "Or"
| Nand -> "Nand"
| Nor -> "Nor"
| Xor -> "Xor"
| Not -> "Not"
let pp_op = function
| Arithmetic(an_op) -> Printf.sprintf "Arithmetic(%s)" (pp_arith an_op)
| NumTest(an_op) -> Printf.sprintf "NumTest(%s)" (pp_numtest an_op)
| CombTest(an_op) -> Printf.sprintf "CombTest(%s)" (pp_combtest an_op)
let pp_str_list stringer a_list depth = Printf.sprintf "[ %s ]" (String.concat ", " (List.map stringer a_list))
let pp_opt stringer = function
| None -> "None"
| Some(v) -> Printf.sprintf "Some(%s)" (stringer v)
let rec pp_expr depth = function
| Id(id) -> Printf.sprintf "Id(%s)" id
| This -> "This"
| Null -> "Null"
| NewObj(the_type, args) -> Printf.sprintf("\n%sNewObj(%s, %s)") (indent depth) the_type (pp_str_list (pp_expr depth) args depth)
| Anonymous(the_type, args, body) -> Printf.sprintf("\n%sAnonymous(%s, %s, %s)") (indent depth) the_type (pp_str_list (pp_expr depth) args depth) (pp_str_list (pp_func_def depth) body depth)
| Literal(l) -> Printf.sprintf "\n%sLiteral(%s)" (indent depth) (pp_lit l)
| Invoc(receiver, meth, args) -> Printf.sprintf "\n%sInvocation(%s, %s, %s)" (indent depth) ((pp_expr (depth+1)) receiver) meth (pp_str_list (pp_expr (depth+1)) args depth)
| Field(receiver, field) -> Printf.sprintf "\n%sField(%s, %s)" (indent depth) ((pp_expr depth) receiver) field
| Deref(var, index) -> Printf.sprintf "\n%sDeref(%s, %s)" (indent depth) ((pp_expr depth) var) ((pp_expr depth) var)
| Unop(an_op, exp) -> Printf.sprintf "\n%sUnop(%s, %s)" (indent depth) (pp_op an_op) ((pp_expr depth) exp)
| Binop(left, an_op, right) -> Printf.sprintf "\n%sBinop(%s, %s, %s)" (indent depth) (pp_op an_op) ((pp_expr depth) left) ((pp_expr depth) right)
| Refine(fname, args, totype) -> Printf.sprintf "Refine(%s, %s, %s)" fname (pp_str_list (pp_expr (depth+1)) args (depth+1)) (pp_opt _id totype)
| Assign(the_var, the_expr) -> Printf.sprintf "\n%sAssign(%s, %s)" (indent depth) ((pp_expr (depth+1)) the_var) ((pp_expr (depth+1)) the_expr)
| Refinable(the_var) -> Printf.sprintf "\n%sRefinable(%s)" (indent depth) the_var
and pp_var_def depth (the_type, the_var) = Printf.sprintf "\n%s(%s, %s)" (indent depth) the_type the_var
and pp_stmt depth = function
| Decl(the_def, the_expr) -> Printf.sprintf "\n%sDecl(%s, %s)" (indent depth) ((pp_var_def (depth+1)) the_def) (pp_opt (pp_expr depth) the_expr)
| If(clauses) -> Printf.sprintf "\n%sIf(%s)" (indent depth) (pp_str_list (inspect_clause depth) clauses depth)
| While(pred, body) -> Printf.sprintf "\n%sWhile(%s, %s)" (indent depth) ((pp_expr depth) pred) (pp_str_list (pp_stmt (depth+1)) body depth)
| Expr(the_expr) -> Printf.sprintf "\n%sExpr(%s)" (indent depth) ((pp_expr (depth+1)) the_expr)
| Return(the_expr) -> Printf.sprintf "\n%sReturn(%s)" (indent depth) (pp_opt (pp_expr depth) the_expr)
| Super(args) -> Printf.sprintf "\n%sSuper(%s)" (indent depth) (pp_str_list (pp_expr depth) args depth)
and inspect_clause depth (opt_expr, body) = Printf.sprintf "(%s, %s)" (pp_opt (pp_expr depth) opt_expr) (pp_str_list (pp_stmt (depth+1)) body depth)
and class_section = function
| Publics -> "Publics"
| Protects -> "Protects"
| Privates -> "Privates"
| Refines -> "Refines"
| Mains -> "Mains"
and pp_func_def depth func = Printf.sprintf "\n%s{\n%sreturns = %s,\n%shost = %s,\n%sname = %s,\n%sstatic = %B,\n%sformals = %s,\n%sbody = %s,\n%ssection = %s,\n%sinklass = %s,\n%suid = %s\n%s}"
(indent (depth-1))
(indent depth)
(pp_opt _id func.returns)
(indent depth)
(pp_opt _id func.host)
(indent depth)
func.name
(indent depth)
func.static
(indent depth)
(pp_str_list (pp_var_def (depth+1)) func.formals depth)
(indent depth)
(pp_str_list (pp_stmt (depth+1)) func.body depth)
(indent depth)
(class_section func.section)
(indent depth)
func.inklass
(indent depth)
func.uid
(indent (depth-1))
let pp_member_def depth = function
| VarMem(vmem) -> Printf.sprintf "\n%sVarMem(%s)" (indent depth) (pp_var_def (depth+1) vmem)
| MethodMem(mmem) -> Printf.sprintf "\n%sMethodMem(%s)" (indent depth) (pp_func_def (depth+1) mmem)
| InitMem(imem) ->
Format.sprintf "\n%sInitMem(%s)@]"
(indent depth) (pp_func_def (depth+1) imem)
let pp_class_sections sections depth =
Format.sprintf "@[<v 3>@,{@[<v 2>@,privates = %s,@,protects = %s,@,publics = %s,@,refines = %s,@,mains = %s@]@,}@]"
(pp_str_list (pp_member_def (depth+1)) sections.privates depth)
(pp_str_list (pp_member_def (depth+1)) sections.protects depth)
(pp_str_list (pp_member_def (depth+1)) sections.publics depth)
(pp_str_list (pp_func_def (depth+1)) sections.refines depth)
(pp_str_list (pp_func_def (depth+1)) sections.mains depth)
let pp_class_def the_klass =
Format.sprintf "@[<v>@,{@[<v 2>@,klass = %s,@,parent = %s,@,sections = %s@]@,}@]"
the_klass.klass
(pp_opt _id the_klass.parent)
(pp_class_sections the_klass.sections 3)