stringify.ml 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. | Allocate (name, dims) ->
  105. [name ^ " = __allocate(" ^ String.concat ", " (List.map node2str dims) ^ ");"]
  106. | Statements stats -> List.concat (List.map node2lines stats)
  107. (* Catch-all, whould never happen *)
  108. | _ -> failwith "invalid node"
  109. (* node -> string *)
  110. and node2str node =
  111. let concat sep nodes = String.concat sep (List.map node2str nodes) in
  112. match node with
  113. (* Global *)
  114. | Program (decls, _) ->
  115. let decl2str decl = String.concat "\n" (node2lines decl) in
  116. String.concat "\n\n" (List.map decl2str decls)
  117. | Param (param_type, name) -> (type2str param_type) ^ " " ^ name
  118. (* Expressions *)
  119. | BoolConst b -> string_of_bool b
  120. | IntConst i -> string_of_int i
  121. | FloatConst f -> string_of_float f
  122. | ArrayConst dims -> "[" ^ concat ", " dims ^ "]"
  123. | ArrayScalar value -> node2str value
  124. | Var v -> v
  125. | Deref (name, dims) -> name ^ (node2str (ArrayConst dims))
  126. | Monop (op, opnd) -> monop2str op ^ node2str opnd
  127. | Binop (op, left, right) ->
  128. "(" ^ node2str left ^ binop2str op ^ node2str right ^ ")"
  129. | Cond (cond, t, f) ->
  130. (node2str cond) ^ " ? " ^ node2str t ^ " : " ^ node2str f
  131. | TypeCast (ctype, value) ->
  132. "(" ^ type2str ctype ^ ")" ^ node2str value
  133. | FunCall (name, args) ->
  134. name ^ "(" ^ (concat ", " args) ^ ")"
  135. | node -> String.concat "\n" (node2lines node)