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 (* For printing error messages *)
192 (* For printing AST *)
193 let op_to_string op =
196 | MinusOp -> "MinusOp"
197 | TimesOp -> "TimesOp"
198 | DivideOp -> "DivideOp"
206 let xs_to_string ?(sep=",") ~f ~indent xs =
207 let i = Indent.to_string indent in
208 xs |> List.map ~f:(fun x -> i ^ (f x)) |> String.concat ~sep
210 let mexp name params ~indent =
211 let params = xs_to_string ~f:(fun x -> x) ~indent params in
212 sprintf "%s[%s]" name params
214 let field_to_string ~indent (Field {name; typ; _}) =
215 let name = Sym.to_string name in
216 let typ = Sym.to_string typ in
217 let indent = Indent.to_string indent in
218 sprintf "%s%s : %s" indent name typ
220 let fields_to_string fields ~indent =
221 let fields = List.map fields ~f:(field_to_string ~indent) in
222 mexp "" fields ~indent
224 let rec exp_to_string ~indent exp =
225 let indent = Indent.next indent in
226 let mexp = mexp ~indent in
231 mexp "IntExp" [(string_of_int i)]
232 | StringExp {string; _} ->
233 mexp "StringExp" [sprintf "%S" string]
234 | CallExp {func; args; _} ->
235 let func = Sym.to_string func in
236 let args = List.map args ~f:(exp_to_string ~indent) in
237 mexp "CallExp" [func; mexp "" args]
238 | OpExp {left; oper; right; _} ->
240 let indent = Indent.next indent in
241 let oper = op_to_string oper in
242 let left = exp_to_string ~indent left in
243 let right = exp_to_string ~indent right in
244 mexp oper [left; right]
246 mexp "OpExp" [op_exp]
247 | RecordExp {fields; typ; _} ->
249 List.map fields ~f:(fun (sym, exp, _) ->
253 (exp_to_string ~indent exp)
256 let typ = Sym.to_string typ in
257 mexp "RecordExp" [typ; mexp "" fields]
260 |> List.map ~f:(fun (e, _) -> exp_to_string e ~indent)
262 | AssignExp {var; exp; _} ->
263 let var = var_to_string ~indent var in
264 let exp = exp_to_string ~indent exp in
265 mexp "AssignExp" [var; exp]
266 | IfExp {test; then'; else'; _} ->
267 let test = exp_to_string ~indent test in
268 let then' = exp_to_string ~indent then' in
271 mexp "IfThen" [test; then']
273 mexp "IfThenElse" [test; then'; (exp_to_string ~indent e)]
275 | WhileExp {test; body; _} ->
276 let test = exp_to_string ~indent test in
277 let body = exp_to_string ~indent body in
278 mexp "WhileExp" [test; body]
279 | ForExp {var; lo; hi; body; _} ->
281 [ (Sym.to_string var)
282 ; (exp_to_string ~indent lo)
283 ; (exp_to_string ~indent hi)
284 ; (exp_to_string ~indent body)
288 | LetExp {decs; body; _} ->
289 let decs = List.map decs ~f:(dec_to_string ~indent) in
290 let body = exp_to_string ~indent body in
291 mexp "LetExp" [mexp "" decs; body]
292 | ArrayExp {typ; size; init; _} ->
293 let typ = Sym.to_string typ in
294 let size = exp_to_string ~indent size in
295 let init = exp_to_string ~indent init in
296 mexp "ArrayExp" [typ; size; init]
298 mexp "VarExp" [(var_to_string ~indent var)]
300 and var_to_string ~indent var =
301 let indent = Indent.next indent in
302 let mexp = mexp ~indent in
304 | SimpleVar {symbol; _} ->
305 mexp "SimpleVar" [(Sym.to_string symbol)]
306 | FieldVar {var; symbol; _} ->
308 [ (var_to_string ~indent var)
309 ; (Sym.to_string symbol)
311 | SubscriptVar {var; exp; _} ->
312 mexp "SubscriptVar[%s]"
313 [ (var_to_string ~indent var)
314 ; (exp_to_string ~indent exp)
316 and dec_to_string ~indent dec =
317 let indent = Indent.next indent in
318 let mexp = mexp ~indent in
320 | VarDec {name; typ; init; _} ->
321 let name = Sym.to_string name in
322 let init = exp_to_string ~indent init in
325 let typ = Sym.to_string typ in
326 mexp "VarDec" [name; typ; init]
328 mexp "VarDec" [name; init]
330 | TypeDecs type_decs ->
332 (List.map type_decs ~f:(type_dec_to_string ~indent))
333 | FunDecs fun_decs ->
335 (List.map fun_decs ~f:(fun_dec_to_string ~indent))
336 and fun_dec_to_string ~indent fun_dec =
337 let indent = Indent.next indent in
338 let mexp = mexp ~indent in
340 | FunDec {name; params; body; _} ->
341 let name = Sym.to_string name in
342 let params = fields_to_string ~indent params in
343 let body = exp_to_string ~indent body in
344 mexp "FunDec" [name; params; body]
345 and type_dec_to_string ~indent type_dec =
346 let indent = Indent.next indent in
347 let mexp = mexp ~indent in
349 | TypeDec {name; ty; _} ->
351 [ (Sym.to_string name)
352 ; (ty_to_string ~indent ty)
354 and ty_to_string ~indent ty =
355 let mexp = mexp ~indent in
357 | NameTy {symbol; _} -> mexp "NameTy" [(Sym.to_string symbol)]
358 | ArrayTy {symbol; _} -> mexp "ArrayTy" [(Sym.to_string symbol)]
359 | RecordTy fields -> mexp "RecordTy" [(fields_to_string ~indent fields)]
362 let unit = String.make 4 ' ' in
363 let indent = Indent.init ~enabled:true ~unit in
364 exp_to_string ~indent