3 module List = ListLabels
4 module String = StringLabels
6 module Sym = Tiger_symbol
7 module Pos = Tiger_position
11 val init : enabled:bool -> unit:string -> t
13 val to_string : t -> string
16 { unit : string option
20 let init ~enabled ~unit =
21 { unit = if enabled then Some unit else None
26 {t with levels = succ t.levels}
28 let to_string = function
31 | {unit=Some u; levels} ->
32 let rec add = function
34 | n -> u ^ (add (pred n))
71 { fields : (Sym.t * exp * Pos.t) list
95 ; escape : bool ref (* Whoa - why a mutable cell in AST? *)
132 | FunDecs of (* "FunctionDec" in Appel's code *)
136 ; escape : bool ref (* Again, why mutable? *)
137 ; typ : (Sym.t * Pos.t) option
141 | TypeDecs of (* "TypeDec" in Appel's code *)
162 | TypeDec of (* An anonymous record in Appel's code *)
170 ; params : field list
171 ; result : (Sym.t * Pos.t) option
178 let op_to_string op =
181 | MinusOp -> "MinusOp"
182 | TimesOp -> "TimesOp"
183 | DivideOp -> "DivideOp"
191 let xs_to_string ?(sep=",") ~f ~indent xs =
192 let i = Indent.to_string indent in
193 xs |> List.map ~f:(fun x -> i ^ (f x)) |> String.concat ~sep
195 let mexp name params ~indent =
196 let params = xs_to_string ~f:(fun x -> x) ~indent params in
197 sprintf "%s[%s]" name params
199 let field_to_string ~indent (Field {name; typ; _}) =
200 let name = Sym.to_string name in
201 let typ = Sym.to_string typ in
202 let indent = Indent.to_string indent in
203 sprintf "%s%s : %s" indent name typ
205 let fields_to_string fields ~indent =
206 let fields = List.map fields ~f:(field_to_string ~indent) in
207 mexp "" fields ~indent
209 let rec exp_to_string ~indent exp =
210 let indent = Indent.next indent in
211 let mexp = mexp ~indent in
216 mexp "IntExp" [(string_of_int i)]
217 | StringExp {string; _} ->
218 mexp "StringExp" [sprintf "%S" string]
219 | CallExp {func; args; _} ->
220 let func = Sym.to_string func in
221 let args = List.map args ~f:(exp_to_string ~indent) in
222 mexp "CallExp" [func; mexp "" args]
223 | OpExp {left; oper; right; _} ->
225 let indent = Indent.next indent in
226 let oper = op_to_string oper in
227 let left = exp_to_string ~indent left in
228 let right = exp_to_string ~indent right in
229 mexp oper [left; right]
231 mexp "OpExp" [op_exp]
232 | RecordExp {fields; typ; _} ->
234 List.map fields ~f:(fun (sym, exp, _) ->
238 (exp_to_string ~indent exp)
241 let typ = Sym.to_string typ in
242 mexp "RecordExp" [typ; mexp "" fields]
245 |> List.map ~f:(fun (e, _) -> exp_to_string e ~indent)
247 | AssignExp {var; exp; _} ->
248 let var = var_to_string ~indent var in
249 let exp = exp_to_string ~indent exp in
250 mexp "AssignExp" [var; exp]
251 | IfExp {test; then'; else'; _} ->
252 let test = exp_to_string ~indent test in
253 let then' = exp_to_string ~indent then' in
256 mexp "IfThen" [test; then']
258 mexp "IfThenElse" [test; then'; (exp_to_string ~indent e)]
260 | WhileExp {test; body; _} ->
261 let test = exp_to_string ~indent test in
262 let body = exp_to_string ~indent body in
263 mexp "WhileExp" [test; body]
264 | ForExp {var; lo; hi; body; _} ->
266 [ (Sym.to_string var)
267 ; (exp_to_string ~indent lo)
268 ; (exp_to_string ~indent hi)
269 ; (exp_to_string ~indent body)
273 | LetExp {decs; body; _} ->
274 let decs = List.map decs ~f:(dec_to_string ~indent) in
275 let body = exp_to_string ~indent body in
276 mexp "LetExp" [mexp "" decs; body]
277 | ArrayExp {typ; size; init; _} ->
278 let typ = Sym.to_string typ in
279 let size = exp_to_string ~indent size in
280 let init = exp_to_string ~indent init in
281 mexp "ArrayExp" [typ; size; init]
283 mexp "VarExp" [(var_to_string ~indent var)]
285 and var_to_string ~indent var =
286 let indent = Indent.next indent in
287 let mexp = mexp ~indent in
289 | SimpleVar {symbol; _} ->
290 mexp "SimpleVar" [(Sym.to_string symbol)]
291 | FieldVar {var; symbol; _} ->
293 [ (var_to_string ~indent var)
294 ; (Sym.to_string symbol)
296 | SubscriptVar {var; exp; _} ->
297 mexp "SubscriptVar[%s]"
298 [ (var_to_string ~indent var)
299 ; (exp_to_string ~indent exp)
301 and dec_to_string ~indent dec =
302 let indent = Indent.next indent in
303 let mexp = mexp ~indent in
305 | VarDec {name; typ; init; _} ->
306 let name = Sym.to_string name in
307 let init = exp_to_string ~indent init in
310 let typ = Sym.to_string typ in
311 mexp "VarDec" [name; typ; init]
313 mexp "VarDec" [name; init]
315 | TypeDecs type_decs ->
317 (List.map type_decs ~f:(type_dec_to_string ~indent))
318 | FunDecs fun_decs ->
320 (List.map fun_decs ~f:(fun_dec_to_string ~indent))
321 and fun_dec_to_string ~indent fun_dec =
322 let indent = Indent.next indent in
323 let mexp = mexp ~indent in
325 | FunDec {name; params; body; _} ->
326 let name = Sym.to_string name in
327 let params = fields_to_string ~indent params in
328 let body = exp_to_string ~indent body in
329 mexp "FunDec" [name; params; body]
330 and type_dec_to_string ~indent type_dec =
331 let indent = Indent.next indent in
332 let mexp = mexp ~indent in
334 | TypeDec {name; ty; _} ->
336 [ (Sym.to_string name)
337 ; (ty_to_string ~indent ty)
339 and ty_to_string ~indent ty =
340 let mexp = mexp ~indent in
342 | NameTy {symbol; _} -> mexp "NameTy" [(Sym.to_string symbol)]
343 | ArrayTy {symbol; _} -> mexp "ArrayTy" [(Sym.to_string symbol)]
344 | RecordTy fields -> mexp "RecordTy" [(fields_to_string ~indent fields)]
347 let unit = String.make 4 ' ' in
348 let indent = Indent.init ~enabled:true ~unit in
349 exp_to_string ~indent