(**************************************************************************) (* *) (* OCaml *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 1996 Institut National de Recherche en Informatique et *) (* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) (* special exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) open Format open Asttypes open Primitive open Types open Lambda let rec struct_const ppf = function | Const_base(Const_int n) -> fprintf ppf "%i" n | Const_base(Const_char c) -> fprintf ppf "%C" c | Const_base(Const_string (s, _)) -> fprintf ppf "%S" s | Const_immstring s -> fprintf ppf "#%S" s | Const_base(Const_float f) -> fprintf ppf "%s" f | Const_base(Const_int32 n) -> fprintf ppf "%lil" n | Const_base(Const_int64 n) -> fprintf ppf "%LiL" n | Const_base(Const_nativeint n) -> fprintf ppf "%nin" n | Const_pointer n -> fprintf ppf "%ia" n | Const_block(tag, []) -> fprintf ppf "[%i]" tag | Const_block(tag, sc1::scl) -> let sconsts ppf scl = List.iter (fun sc -> fprintf ppf "@ %a" struct_const sc) scl in fprintf ppf "@[<1>[%i:@ @[%a%a@]]@]" tag struct_const sc1 sconsts scl | Const_float_array [] -> fprintf ppf "[| |]" | Const_float_array (f1 :: fl) -> let floats ppf fl = List.iter (fun f -> fprintf ppf "@ %s" f) fl in fprintf ppf "@[<1>[|@[%s%a@]|]@]" f1 floats fl let array_kind = function | Pgenarray -> "gen" | Paddrarray -> "addr" | Pintarray -> "int" | Pfloatarray -> "float" let boxed_integer_name = function | Pnativeint -> "nativeint" | Pint32 -> "int32" | Pint64 -> "int64" let print_boxed_integer_conversion ppf bi1 bi2 = fprintf ppf "%s_of_%s" (boxed_integer_name bi2) (boxed_integer_name bi1) let boxed_integer_mark name = function | Pnativeint -> Printf.sprintf "Nativeint.%s" name | Pint32 -> Printf.sprintf "Int32.%s" name | Pint64 -> Printf.sprintf "Int64.%s" name let print_boxed_integer name ppf bi = fprintf ppf "%s" (boxed_integer_mark name bi);; let print_bigarray name unsafe kind ppf layout = fprintf ppf "Bigarray.%s[%s,%s]" (if unsafe then "unsafe_"^ name else name) (match kind with | Pbigarray_unknown -> "generic" | Pbigarray_float32 -> "float32" | Pbigarray_float64 -> "float64" | Pbigarray_sint8 -> "sint8" | Pbigarray_uint8 -> "uint8" | Pbigarray_sint16 -> "sint16" | Pbigarray_uint16 -> "uint16" | Pbigarray_int32 -> "int32" | Pbigarray_int64 -> "int64" | Pbigarray_caml_int -> "camlint" | Pbigarray_native_int -> "nativeint" | Pbigarray_complex32 -> "complex32" | Pbigarray_complex64 -> "complex64") (match layout with | Pbigarray_unknown_layout -> "unknown" | Pbigarray_c_layout -> "C" | Pbigarray_fortran_layout -> "Fortran") let record_rep ppf r = match r with | Record_regular -> fprintf ppf "regular" | Record_inlined i -> fprintf ppf "inlined(%i)" i | Record_float -> fprintf ppf "float" | Record_extension -> fprintf ppf "ext" ;; let string_of_loc_kind = function | Loc_FILE -> "loc_FILE" | Loc_LINE -> "loc_LINE" | Loc_MODULE -> "loc_MODULE" | Loc_POS -> "loc_POS" | Loc_LOC -> "loc_LOC" let primitive ppf = function | Pidentity -> fprintf ppf "id" | Pignore -> fprintf ppf "ignore" | Prevapply _ -> fprintf ppf "revapply" | Pdirapply _ -> fprintf ppf "dirapply" | Ploc kind -> fprintf ppf "%s" (string_of_loc_kind kind) | Pgetglobal id -> fprintf ppf "global %a" Ident.print id | Psetglobal id -> fprintf ppf "setglobal %a" Ident.print id | Pmakeblock(tag, Immutable) -> fprintf ppf "makeblock %i" tag | Pmakeblock(tag, Mutable) -> fprintf ppf "makemutable %i" tag | Pfield n -> fprintf ppf "field %i" n | Psetfield(n, ptr, init) -> let instr = match ptr with | Pointer -> "ptr" | Immediate -> "imm" in let init = match init with | Initialization -> "(init)" | Assignment -> "" in fprintf ppf "setfield_%s%s %i" instr init n | Pfloatfield n -> fprintf ppf "floatfield %i" n | Psetfloatfield (n, init) -> let init = match init with | Initialization -> "(init)" | Assignment -> "" in fprintf ppf "setfloatfield%s %i" init n | Pduprecord (rep, size) -> fprintf ppf "duprecord %a %i" record_rep rep size | Plazyforce -> fprintf ppf "force" | Pccall p -> fprintf ppf "%s" p.prim_name | Praise k -> fprintf ppf "%s" (Lambda.raise_kind k) | Psequand -> fprintf ppf "&&" | Psequor -> fprintf ppf "||" | Pnot -> fprintf ppf "not" | Pnegint -> fprintf ppf "~" | Paddint -> fprintf ppf "+" | Psubint -> fprintf ppf "-" | Pmulint -> fprintf ppf "*" | Pdivint -> fprintf ppf "/" | Pmodint -> fprintf ppf "mod" | Pandint -> fprintf ppf "and" | Porint -> fprintf ppf "or" | Pxorint -> fprintf ppf "xor" | Plslint -> fprintf ppf "lsl" | Plsrint -> fprintf ppf "lsr" | Pasrint -> fprintf ppf "asr" | Pintcomp(Ceq) -> fprintf ppf "==" | Pintcomp(Cneq) -> fprintf ppf "!=" | Pintcomp(Clt) -> fprintf ppf "<" | Pintcomp(Cle) -> fprintf ppf "<=" | Pintcomp(Cgt) -> fprintf ppf ">" | Pintcomp(Cge) -> fprintf ppf ">=" | Poffsetint n -> fprintf ppf "%i+" n | Poffsetref n -> fprintf ppf "+:=%i"n | Pintoffloat -> fprintf ppf "int_of_float" | Pfloatofint -> fprintf ppf "float_of_int" | Pnegfloat -> fprintf ppf "~." | Pabsfloat -> fprintf ppf "abs." | Paddfloat -> fprintf ppf "+." | Psubfloat -> fprintf ppf "-." | Pmulfloat -> fprintf ppf "*." | Pdivfloat -> fprintf ppf "/." | Pfloatcomp(Ceq) -> fprintf ppf "==." | Pfloatcomp(Cneq) -> fprintf ppf "!=." | Pfloatcomp(Clt) -> fprintf ppf "<." | Pfloatcomp(Cle) -> fprintf ppf "<=." | Pfloatcomp(Cgt) -> fprintf ppf ">." | Pfloatcomp(Cge) -> fprintf ppf ">=." | Pstringlength -> fprintf ppf "string.length" | Pstringrefu -> fprintf ppf "string.unsafe_get" | Pstringsetu -> fprintf ppf "string.unsafe_set" | Pstringrefs -> fprintf ppf "string.get" | Pstringsets -> fprintf ppf "string.set" | Parraylength k -> fprintf ppf "array.length[%s]" (array_kind k) | Pmakearray (k, Mutable) -> fprintf ppf "makearray[%s]" (array_kind k) | Pmakearray (k, Immutable) -> fprintf ppf "makearray_imm[%s]" (array_kind k) | Pduparray (k, Mutable) -> fprintf ppf "duparray[%s]" (array_kind k) | Pduparray (k, Immutable) -> fprintf ppf "duparray_imm[%s]" (array_kind k) | Parrayrefu k -> fprintf ppf "array.unsafe_get[%s]" (array_kind k) | Parraysetu k -> fprintf ppf "array.unsafe_set[%s]" (array_kind k) | Parrayrefs k -> fprintf ppf "array.get[%s]" (array_kind k) | Parraysets k -> fprintf ppf "array.set[%s]" (array_kind k) | Pctconst c -> let const_name = match c with | Big_endian -> "big_endian" | Word_size -> "word_size" | Int_size -> "int_size" | Max_wosize -> "max_wosize" | Ostype_unix -> "ostype_unix" | Ostype_win32 -> "ostype_win32" | Ostype_cygwin -> "ostype_cygwin" in fprintf ppf "sys.constant_%s" const_name | Pisint -> fprintf ppf "isint" | Pisout -> fprintf ppf "isout" | Pbittest -> fprintf ppf "testbit" | Pbintofint bi -> print_boxed_integer "of_int" ppf bi | Pintofbint bi -> print_boxed_integer "to_int" ppf bi | Pcvtbint (bi1, bi2) -> print_boxed_integer_conversion ppf bi1 bi2 | Pnegbint bi -> print_boxed_integer "neg" ppf bi | Paddbint bi -> print_boxed_integer "add" ppf bi | Psubbint bi -> print_boxed_integer "sub" ppf bi | Pmulbint bi -> print_boxed_integer "mul" ppf bi | Pdivbint bi -> print_boxed_integer "div" ppf bi | Pmodbint bi -> print_boxed_integer "mod" ppf bi | Pandbint bi -> print_boxed_integer "and" ppf bi | Porbint bi -> print_boxed_integer "or" ppf bi | Pxorbint bi -> print_boxed_integer "xor" ppf bi | Plslbint bi -> print_boxed_integer "lsl" ppf bi | Plsrbint bi -> print_boxed_integer "lsr" ppf bi | Pasrbint bi -> print_boxed_integer "asr" ppf bi | Pbintcomp(bi, Ceq) -> print_boxed_integer "==" ppf bi | Pbintcomp(bi, Cneq) -> print_boxed_integer "!=" ppf bi | Pbintcomp(bi, Clt) -> print_boxed_integer "<" ppf bi | Pbintcomp(bi, Cgt) -> print_boxed_integer ">" ppf bi | Pbintcomp(bi, Cle) -> print_boxed_integer "<=" ppf bi | Pbintcomp(bi, Cge) -> print_boxed_integer ">=" ppf bi | Pbigarrayref(unsafe, _n, kind, layout) -> print_bigarray "get" unsafe kind ppf layout | Pbigarrayset(unsafe, _n, kind, layout) -> print_bigarray "set" unsafe kind ppf layout | Pbigarraydim(n) -> fprintf ppf "Bigarray.dim_%i" n | Pstring_load_16(unsafe) -> if unsafe then fprintf ppf "string.unsafe_get16" else fprintf ppf "string.get16" | Pstring_load_32(unsafe) -> if unsafe then fprintf ppf "string.unsafe_get32" else fprintf ppf "string.get32" | Pstring_load_64(unsafe) -> if unsafe then fprintf ppf "string.unsafe_get64" else fprintf ppf "string.get64" | Pstring_set_16(unsafe) -> if unsafe then fprintf ppf "string.unsafe_set16" else fprintf ppf "string.set16" | Pstring_set_32(unsafe) -> if unsafe then fprintf ppf "string.unsafe_set32" else fprintf ppf "string.set32" | Pstring_set_64(unsafe) -> if unsafe then fprintf ppf "string.unsafe_set64" else fprintf ppf "string.set64" | Pbigstring_load_16(unsafe) -> if unsafe then fprintf ppf "bigarray.array1.unsafe_get16" else fprintf ppf "bigarray.array1.get16" | Pbigstring_load_32(unsafe) -> if unsafe then fprintf ppf "bigarray.array1.unsafe_get32" else fprintf ppf "bigarray.array1.get32" | Pbigstring_load_64(unsafe) -> if unsafe then fprintf ppf "bigarray.array1.unsafe_get64" else fprintf ppf "bigarray.array1.get64" | Pbigstring_set_16(unsafe) -> if unsafe then fprintf ppf "bigarray.array1.unsafe_set16" else fprintf ppf "bigarray.array1.set16" | Pbigstring_set_32(unsafe) -> if unsafe then fprintf ppf "bigarray.array1.unsafe_set32" else fprintf ppf "bigarray.array1.set32" | Pbigstring_set_64(unsafe) -> if unsafe then fprintf ppf "bigarray.array1.unsafe_set64" else fprintf ppf "bigarray.array1.set64" | Pbswap16 -> fprintf ppf "bswap16" | Pbbswap(bi) -> print_boxed_integer "bswap" ppf bi | Pint_as_pointer -> fprintf ppf "int_as_pointer" | Popaque -> fprintf ppf "opaque" let name_of_primitive = function | Pidentity -> "Pidentity" | Pignore -> "Pignore" | Prevapply _ -> "Prevapply" | Pdirapply _ -> "Pdirapply" | Ploc _ -> "Ploc" | Pgetglobal _ -> "Pgetglobal" | Psetglobal _ -> "Psetglobal" | Pmakeblock _ -> "Pmakeblock" | Pfield _ -> "Pfield" | Psetfield _ -> "Psetfield" | Pfloatfield _ -> "Pfloatfield" | Psetfloatfield _ -> "Psetfloatfield" | Pduprecord _ -> "Pduprecord" | Plazyforce -> "Plazyforce" | Pccall _ -> "Pccall" | Praise _ -> "Praise" | Psequand -> "Psequand" | Psequor -> "Psequor" | Pnot -> "Pnot" | Pnegint -> "Pnegint" | Paddint -> "Paddint" | Psubint -> "Psubint" | Pmulint -> "Pmulint" | Pdivint -> "Pdivint" | Pmodint -> "Pmodint" | Pandint -> "Pandint" | Porint -> "Porint" | Pxorint -> "Pxorint" | Plslint -> "Plslint" | Plsrint -> "Plsrint" | Pasrint -> "Pasrint" | Pintcomp _ -> "Pintcomp" | Poffsetint _ -> "Poffsetint" | Poffsetref _ -> "Poffsetref" | Pintoffloat -> "Pintoffloat" | Pfloatofint -> "Pfloatofint" | Pnegfloat -> "Pnegfloat" | Pabsfloat -> "Pabsfloat" | Paddfloat -> "Paddfloat" | Psubfloat -> "Psubfloat" | Pmulfloat -> "Pmulfloat" | Pdivfloat -> "Pdivfloat" | Pfloatcomp _ -> "Pfloatcomp" | Pstringlength -> "Pstringlength" | Pstringrefu -> "Pstringrefu" | Pstringsetu -> "Pstringsetu" | Pstringrefs -> "Pstringrefs" | Pstringsets -> "Pstringsets" | Parraylength _ -> "Parraylength" | Pmakearray _ -> "Pmakearray" | Pduparray _ -> "Pduparray" | Parrayrefu _ -> "Parrayrefu" | Parraysetu _ -> "Parraysetu" | Parrayrefs _ -> "Parrayrefs" | Parraysets _ -> "Parraysets" | Pctconst _ -> "Pctconst" | Pisint -> "Pisint" | Pisout -> "Pisout" | Pbittest -> "Pbittest" | Pbintofint _ -> "Pbintofint" | Pintofbint _ -> "Pintofbint" | Pcvtbint _ -> "Pcvtbint" | Pnegbint _ -> "Pnegbint" | Paddbint _ -> "Paddbint" | Psubbint _ -> "Psubbint" | Pmulbint _ -> "Pmulbint" | Pdivbint _ -> "Pdivbint" | Pmodbint _ -> "Pmodbint" | Pandbint _ -> "Pandbint" | Porbint _ -> "Porbint" | Pxorbint _ -> "Pxorbint" | Plslbint _ -> "Plslbint" | Plsrbint _ -> "Plsrbint" | Pasrbint _ -> "Pasrbint" | Pbintcomp _ -> "Pbintcomp" | Pbigarrayref _ -> "Pbigarrayref" | Pbigarrayset _ -> "Pbigarrayset" | Pbigarraydim _ -> "Pbigarraydim" | Pstring_load_16 _ -> "Pstring_load_16" | Pstring_load_32 _ -> "Pstring_load_32" | Pstring_load_64 _ -> "Pstring_load_64" | Pstring_set_16 _ -> "Pstring_set_16" | Pstring_set_32 _ -> "Pstring_set_32" | Pstring_set_64 _ -> "Pstring_set_64" | Pbigstring_load_16 _ -> "Pbigstring_load_16" | Pbigstring_load_32 _ -> "Pbigstring_load_32" | Pbigstring_load_64 _ -> "Pbigstring_load_64" | Pbigstring_set_16 _ -> "Pbigstring_set_16" | Pbigstring_set_32 _ -> "Pbigstring_set_32" | Pbigstring_set_64 _ -> "Pbigstring_set_64" | Pbswap16 -> "Pbswap16" | Pbbswap _ -> "Pbbswap" | Pint_as_pointer -> "Pint_as_pointer" | Popaque -> "Popaque" let function_attribute ppf { inline; specialise; is_a_functor } = if is_a_functor then fprintf ppf "is_a_functor@ "; begin match inline with | Default_inline -> () | Always_inline -> fprintf ppf "always_inline@ " | Never_inline -> fprintf ppf "never_inline@ " | Unroll i -> fprintf ppf "unroll(%i)@ " i end; begin match specialise with | Default_specialise -> () | Always_specialise -> fprintf ppf "always_specialise@ " | Never_specialise -> fprintf ppf "never_specialise@ " end let apply_tailcall_attribute ppf tailcall = if tailcall then fprintf ppf " @@tailcall" let apply_inlined_attribute ppf = function | Default_inline -> () | Always_inline -> fprintf ppf " always_inline" | Never_inline -> fprintf ppf " never_inline" | Unroll i -> fprintf ppf " never_inline(%i)" i let apply_specialised_attribute ppf = function | Default_specialise -> () | Always_specialise -> fprintf ppf " always_specialise" | Never_specialise -> fprintf ppf " never_specialise" let rec lam ppf = function | Lvar id -> Ident.print ppf id | Lconst cst -> struct_const ppf cst | Lapply ap -> let lams ppf largs = List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in fprintf ppf "@[<2>(apply@ %a%a%a%a%a)@]" lam ap.ap_func lams ap.ap_args apply_tailcall_attribute ap.ap_should_be_tailcall apply_inlined_attribute ap.ap_inlined apply_specialised_attribute ap.ap_specialised | Lfunction{kind; params; body; attr} -> let pr_params ppf params = match kind with | Curried -> List.iter (fun param -> fprintf ppf "@ %a" Ident.print param) params | Tupled -> fprintf ppf " ("; let first = ref true in List.iter (fun param -> if !first then first := false else fprintf ppf ",@ "; Ident.print ppf param) params; fprintf ppf ")" in fprintf ppf "@[<2>(function%a@ %a%a)@]" pr_params params function_attribute attr lam body | Llet(str, id, arg, body) -> let kind = function Alias -> "a" | Strict -> "" | StrictOpt -> "o" | Variable -> "v" in let rec letbody = function | Llet(str, id, arg, body) -> fprintf ppf "@ @[<2>%a =%s@ %a@]" Ident.print id (kind str) lam arg; letbody body | expr -> expr in fprintf ppf "@[<2>(let@ @[(@[<2>%a =%s@ %a@]" Ident.print id (kind str) lam arg; let expr = letbody body in fprintf ppf ")@]@ %a)@]" lam expr | Lletrec(id_arg_list, body) -> let bindings ppf id_arg_list = let spc = ref false in List.iter (fun (id, l) -> if !spc then fprintf ppf "@ " else spc := true; fprintf ppf "@[<2>%a@ %a@]" Ident.print id lam l) id_arg_list in fprintf ppf "@[<2>(letrec@ (@[%a@])@ %a)@]" bindings id_arg_list lam body | Lprim(prim, largs) -> let lams ppf largs = List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in fprintf ppf "@[<2>(%a%a)@]" primitive prim lams largs | Lswitch(larg, sw) -> let switch ppf sw = let spc = ref false in List.iter (fun (n, l) -> if !spc then fprintf ppf "@ " else spc := true; fprintf ppf "@[case int %i:@ %a@]" n lam l) sw.sw_consts; List.iter (fun (n, l) -> if !spc then fprintf ppf "@ " else spc := true; fprintf ppf "@[case tag %i:@ %a@]" n lam l) sw.sw_blocks ; begin match sw.sw_failaction with | None -> () | Some l -> if !spc then fprintf ppf "@ " else spc := true; fprintf ppf "@[default:@ %a@]" lam l end in fprintf ppf "@[<1>(%s %a@ @[%a@])@]" (match sw.sw_failaction with None -> "switch*" | _ -> "switch") lam larg switch sw | Lstringswitch(arg, cases, default) -> let switch ppf cases = let spc = ref false in List.iter (fun (s, l) -> if !spc then fprintf ppf "@ " else spc := true; fprintf ppf "@[case \"%s\":@ %a@]" (String.escaped s) lam l) cases; begin match default with | Some default -> if !spc then fprintf ppf "@ " else spc := true; fprintf ppf "@[default:@ %a@]" lam default | None -> () end in fprintf ppf "@[<1>(stringswitch %a@ @[%a@])@]" lam arg switch cases | Lstaticraise (i, ls) -> let lams ppf largs = List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in fprintf ppf "@[<2>(exit@ %d%a)@]" i lams ls; | Lstaticcatch(lbody, (i, vars), lhandler) -> fprintf ppf "@[<2>(catch@ %a@;<1 -1>with (%d%a)@ %a)@]" lam lbody i (fun ppf vars -> match vars with | [] -> () | _ -> List.iter (fun x -> fprintf ppf " %a" Ident.print x) vars) vars lam lhandler | Ltrywith(lbody, param, lhandler) -> fprintf ppf "@[<2>(try@ %a@;<1 -1>with %a@ %a)@]" lam lbody Ident.print param lam lhandler | Lifthenelse(lcond, lif, lelse) -> fprintf ppf "@[<2>(if@ %a@ %a@ %a)@]" lam lcond lam lif lam lelse | Lsequence(l1, l2) -> fprintf ppf "@[<2>(seq@ %a@ %a)@]" lam l1 sequence l2 | Lwhile(lcond, lbody) -> fprintf ppf "@[<2>(while@ %a@ %a)@]" lam lcond lam lbody | Lfor(param, lo, hi, dir, body) -> fprintf ppf "@[<2>(for %a@ %a@ %s@ %a@ %a)@]" Ident.print param lam lo (match dir with Upto -> "to" | Downto -> "downto") lam hi lam body | Lassign(id, expr) -> fprintf ppf "@[<2>(assign@ %a@ %a)@]" Ident.print id lam expr | Lsend (k, met, obj, largs, _) -> let args ppf largs = List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in let kind = if k = Self then "self" else if k = Cached then "cache" else "" in fprintf ppf "@[<2>(send%s@ %a@ %a%a)@]" kind lam obj lam met args largs | Levent(expr, ev) -> let kind = match ev.lev_kind with | Lev_before -> "before" | Lev_after _ -> "after" | Lev_function -> "funct-body" | Lev_pseudo -> "pseudo" in fprintf ppf "@[<2>(%s %s(%i)%s:%i-%i@ %a)@]" kind ev.lev_loc.Location.loc_start.Lexing.pos_fname ev.lev_loc.Location.loc_start.Lexing.pos_lnum (if ev.lev_loc.Location.loc_ghost then "" else "") ev.lev_loc.Location.loc_start.Lexing.pos_cnum ev.lev_loc.Location.loc_end.Lexing.pos_cnum lam expr | Lifused(id, expr) -> fprintf ppf "@[<2>(ifused@ %a@ %a)@]" Ident.print id lam expr and sequence ppf = function | Lsequence(l1, l2) -> fprintf ppf "%a@ %a" sequence l1 sequence l2 | l -> lam ppf l let structured_constant = struct_const let lambda = lam let program ppf { code } = lambda ppf code