(* Printing *)
(* Author: Frank Pfenning *)
(* Modified: Jeff Polakow *)
(* Modified: Carsten Schuermann *)
functor PrintOMDoc
((*! structure IntSyn' : INTSYN !*)
structure Whnf : WHNF
(*! sharing Whnf.IntSyn = IntSyn' !*)
structure Abstract : ABSTRACT
(*! sharing Abstract.IntSyn = IntSyn' !*)
structure Constraints : CONSTRAINTS
(*! sharing Constraints.IntSyn = IntSyn' !*)
structure Names : NAMES
(*! sharing Names.IntSyn = IntSyn' !*)
structure Formatter' : FORMATTER)
: PRINT_XML =
struct
(*! structure IntSyn = IntSyn' !*)
structure Formatter = Formatter'
local
(* Shorthands *)
structure I = IntSyn
structure F = Formatter
fun escape nil = nil
| escape (#"&" :: rest) = String.explode "&" @ (escape rest)
| escape (#"<" :: rest) = String.explode "<" @ (escape rest)
| escape (#">" :: rest) = String.explode ">" @ (escape rest)
| escape (c :: rest) = c :: (escape rest)
val Str = F.String
fun Str0 (s, n) = F.String0 n s
fun Name (x) = F.String ("\"" ^ (String.implode (escape (String.explode x))) ^ "\"")
fun Integer (n) = F.String ("\"" ^ Int.toString n ^ "\"")
fun sexp (fmts) = F.Hbox [F.HVbox fmts]
(* fmtCon (c) = "c" where the name is assigned according the the Name table
maintained in the names module.
FVar's are printed with a preceding "`" (backquote) character
*)
fun fmtCon (G, I.BVar(n)) =
let
val I.Dec (SOME n, _) = I.ctxDec (G, n)
in
sexp [Str ("")]
end
| fmtCon (G, I.Const(cid)) = sexp [Str ""]
| fmtCon (G, I.Def(cid)) = sexp [Str ""]
(* I.Skonst, I.FVar cases should be impossible *)
(* fmtUni (L) = "L" *)
fun fmtUni (I.Type) = Str ""
| fmtUni (I.Kind) = Str ""
(* fmtExpW (G, (U, s)) = fmt
format the expression U[s].
Invariants:
G is a "printing context" (names in it are unique, but
types may be incorrect) approximating G'
G'' |- U : V G' |- s : G'' (so G' |- U[s] : V[s])
(U,s) in whnf
*)
fun fmtExpW (G, (I.Uni(L), s)) = sexp [fmtUni L]
| fmtExpW (G, (I.Pi((D as I.Dec(_,V1),P),V2), s)) =
(case P (* if Pi is dependent but anonymous, invent name here *)
of I.Maybe => let
val (D' as I.Dec (SOME(x), V1')) = Names.decLUName (G, D) (* could sometimes be EName *)
val G' = I.Decl (G, D')
val fmtType = fmtExp (G, (V1', s))
in
sexp [Str " ",
F.Break, Str "", F.Break, Str "", F.Break,
Str "", F.Break,
Str "", F.Break,
fmtType, F.Break, Str "", F.Break,
Str "",
F.Break, fmtExp (G', (V2, I.dot1 s)), Str ""]
end
| I.No => let
val G' = I.Decl (G, D)
in
sexp [Str "", F.Break, Str "",
fmtExp (G, (V1, s)),
F.Break, (* Str "tw*no", F.Break,*) fmtExp (G', (V2, I.dot1 s)),
Str ""]
end)
| fmtExpW (G, (I.Root (H, S), s)) =
(case (fmtSpine (G, (S, s)))
of NONE => fmtCon (G, H)
| SOME fmts => F.HVbox [Str "", fmtCon (G, H),
F.Break, sexp (fmts), Str ""])
| fmtExpW (G, (I.Lam(D, U), s)) =
let
val (D' as I.Dec (SOME(x), V)) = Names.decLUName (G, D)
val G' = I.Decl (G, D')
val fmtType = fmtExp (G, (V, s))
in
sexp [Str " ",
F.Break, Str "", F.Break, Str "", F.Break,
Str "", F.Break,
Str "", F.Break,
fmtType, F.Break, Str "", F.Break,
Str "",
F.Break, fmtExp (G', (U, I.dot1 s)), Str ""]
end
(* I.EClo, I.Redex, I.EVar not possible *)
and fmtExp (G, (U, s)) = fmtExpW (G, Whnf.whnf (U, s))
(* fmtSpine (G, (S, s)) = fmts
format spine S[s] at printing depth d, printing length l, in printing
context G which approximates G', where G' |- S[s] is valid
*)
and fmtSpine (G, (I.Nil, _)) = NONE
| fmtSpine (G, (I.SClo (S, s'), s)) =
fmtSpine (G, (S, I.comp(s',s)))
| fmtSpine (G, (I.App(U, S), s)) =
(case (fmtSpine (G, (S, s)))
of NONE => SOME [fmtExp (G, (U, s))]
| SOME fmts => SOME ([fmtExp (G, (U, s)), F.Break] @ fmts))
fun fmtExpTop (G, (U, s)) = sexp [Str "", fmtExp (G, (U, s)), Str ""]
(* fmtConDec (condec) = fmt
formats a constant declaration (which must be closed and in normal form)
This function prints the quantifiers and abstractions only if hide = false.
*)
fun fmtConDec (I.ConDec (name, parent, imp, _, V, L)) =
let
val _ = Names.varReset IntSyn.Null
in
sexp [Str "", F.Break, Str "",
F.Break, fmtExpTop (I.Null, (V, I.id)),
Str ""]
end
| fmtConDec (I.SkoDec (name, parent, imp, V, L)) =
Str ("")
| fmtConDec (I.ConDef (name, parent, imp, U, V, L, _)) =
let
val _ = Names.varReset IntSyn.Null
in
sexp [Str "",
F.Break, Str "",
F.Break, fmtExpTop (I.Null, (V, I.id)),
Str "", F.Break,
Str "",fmtExpTop (I.Null, (U, I.id)),
Str ""]
end
| fmtConDec (I.AbbrevDef (name, parent, imp, U, V, L)) =
let
val _ = Names.varReset IntSyn.Null
in
sexp [Str "",
F.Break, Str "",
F.Break, fmtExpTop (I.Null, (V, I.id)),
Str "", F.Break,
Str "",fmtExpTop (I.Null, (U, I.id)),
Str ""]
end
| fmtConDec (I.BlockDec (name, _, _, _)) =
Str ("")
in
(* In the functions below, G must be a "printing context", that is,
(a) unique names must be assigned to each declaration which may
actually applied in the scope (typically, using Names.decName)
(b) types need not be well-formed, since they are not used
*)
fun formatExp (G, U) = fmtExp (G, (U, I.id))
(* fun formatSpine (G, S) = sexp (fmtSpine (G, (S, I.id))) *)
fun formatConDec (condec) = fmtConDec (condec)
fun expToString (G, U) = F.makestring_fmt (formatExp (G, U))
fun conDecToString (condec) = F.makestring_fmt (formatConDec (condec))
fun printSgn () =
IntSyn.sgnApp (fn (cid) => (print (F.makestring_fmt (formatConDec (IntSyn.sgnLookup cid)));
print "\n"))
fun printSgnToFile path filename =
let
val file = TextIO.openOut (path ^ filename)
val _ = TextIO.output (file, "\n\n\n\n\n\n")
val _ = IntSyn.sgnApp (fn (cid) => (TextIO.output (file, F.makestring_fmt (formatConDec (IntSyn.sgnLookup cid)));
TextIO.output (file, "\n")))
val _ = TextIO.output (file, "")
val _ = TextIO.closeOut file
in
()
end
end (* local ... *)
end (* functor PrintXml *)