stringify.ml 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. open Ast
  2. let tab = " "
  3. (* int -> string list -> string list *)
  4. let indent (lines : string list) =
  5. let prepend_tab line = tab ^ line in
  6. List.map prepend_tab lines
  7. (* monop -> string *)
  8. let monop2str = function
  9. | Neg -> "-"
  10. | Not -> "!"
  11. (* binop -> string *)
  12. let binop2str = function
  13. | Add -> " + "
  14. | Sub -> " - "
  15. | Mul -> " * "
  16. | Div -> " / "
  17. | Mod -> " % "
  18. | Eq -> " == "
  19. | Ne -> " != "
  20. | Lt -> " < "
  21. | Le -> " <= "
  22. | Gt -> " > "
  23. | Ge -> " >= "
  24. | And -> " && "
  25. | Or -> " || "
  26. (* ctype -> string *)
  27. let rec type2str = function
  28. | Void -> "void"
  29. | Bool -> "bool"
  30. | Int -> "int"
  31. | Float -> "float"
  32. | ArrayDec (t, dims) -> (type2str t) ^ "[" ^ (String.concat ", " dims) ^ "]"
  33. | ArrayDef (t, dims) -> (type2str t) ^ "[" ^ (String.concat ", " (List.map node2str dims)) ^ "]"
  34. (* decl -> string list *)
  35. and node2lines node =
  36. let all_str = List.map node2str in
  37. let all_lines = List.map node2lines in
  38. match node with
  39. (* Decls *)
  40. | FunDec (ret_type, name, params) ->
  41. let params = String.concat ", " (all_str params) in
  42. ["extern " ^ (type2str ret_type) ^ " " ^ name ^ "(" ^ params ^ ");"]
  43. | FunDef (export, ret_type, name, params, body) ->
  44. let export = if export then "export " else "" in
  45. let params = String.concat ", " (all_str params) in
  46. let header = (type2str ret_type) ^ " " ^ name ^ "(" ^ params ^ ")" in
  47. let body = indent (List.concat (all_lines body)) in
  48. [export ^ header ^ " {"] @
  49. body @
  50. ["}"]
  51. | GlobalDec (var_type, name) ->
  52. ["extern " ^ (type2str var_type) ^ " " ^ name ^ ";"]
  53. | GlobalDef (export, ret_type, name, init) ->
  54. let export = if export then "export " else "" in
  55. let init = match init with
  56. | Some value -> " = " ^ (node2str value)
  57. | None -> ""
  58. in
  59. [export ^ (type2str ret_type) ^ " " ^ name ^ init ^ ";"]
  60. (* Statements *)
  61. | VarDec (var_type, name, None) ->
  62. [(type2str var_type) ^ " " ^ name ^ ";"]
  63. | VarDec (var_type, name, Some init) ->
  64. [(type2str var_type) ^ " " ^ name ^ " = " ^ (node2str init) ^ ";"]
  65. | Assign (name, value) ->
  66. [name ^ " = " ^ (node2str value) ^ ";"]
  67. | Expr expr ->
  68. [node2str expr ^ ";"]
  69. | Return value ->
  70. ["return " ^ (node2str value) ^ ";"]
  71. | If (cond, body) ->
  72. let body = indent (List.concat (all_lines body)) in
  73. ["if (" ^ (node2str cond) ^ ") {"] @
  74. body @
  75. ["}"]
  76. | IfElse (cond, true_body, false_body) ->
  77. let true_body = indent (List.concat (all_lines true_body)) in
  78. let false_body = indent (List.concat (all_lines false_body)) in
  79. ["if (" ^ (node2str cond) ^ ") {"] @
  80. true_body @
  81. ["} else {"] @
  82. false_body @
  83. ["}"]
  84. | While (cond, body) ->
  85. let body = indent (List.concat (all_lines body)) in
  86. ["while (" ^ (node2str cond) ^ ") {"] @
  87. body @
  88. ["}"]
  89. | DoWhile (cond, body) ->
  90. let body = indent (List.concat (all_lines body)) in
  91. ["do {"] @
  92. body @
  93. ["} while (" ^ (node2str cond) ^ ");"]
  94. | For (counter, start, stop, step, body) ->
  95. let step = match step with
  96. | IntConst 1 -> ""
  97. | value -> ", " ^ (node2str value)
  98. in
  99. let range = (node2str start) ^ ", " ^ (node2str stop) ^ step in
  100. let body = indent (List.concat (all_lines body)) in
  101. ["for (int " ^ counter ^ " = " ^ range ^ ") {"] @
  102. body @
  103. ["}"]
  104. (* Catch-all, whould never happen *)
  105. | _ -> failwith "invalid node"
  106. (* node -> string *)
  107. and node2str = function
  108. (* Global *)
  109. | Program decls ->
  110. let decl2str decl = String.concat "\n" (node2lines decl) in
  111. String.concat "\n\n" (List.map decl2str decls)
  112. | Param (param_type, name) -> (type2str param_type) ^ " " ^ name
  113. (* Expressions *)
  114. | BoolConst b -> string_of_bool b
  115. | IntConst i -> string_of_int i
  116. | FloatConst f -> string_of_float f
  117. | ArrayConst dims -> "[" ^ (String.concat ", " (List.map node2str dims)) ^ "]"
  118. | Var v -> v
  119. | Deref (name, dims) -> name ^ (node2str (ArrayConst dims))
  120. | Monop (op, opnd) -> monop2str op ^ node2str opnd
  121. | Binop (op, left, right) ->
  122. "(" ^ node2str left ^ binop2str op ^ node2str right ^ ")"
  123. | Cond (cond, t, f) ->
  124. (node2str cond) ^ " ? " ^ (node2str t) ^ " : " ^ (node2str f)
  125. | TypeCast (ctype, value) ->
  126. "(" ^ (type2str ctype) ^ ")" ^ (node2str value)
  127. | FunCall (name, args) ->
  128. name ^ "(" ^ (String.concat ", " (List.map node2str args)) ^ ")"
  129. | node -> String.concat "\n" (node2lines node)