Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: code_printer.ML   Sprache: SML

Original von: Isabelle©

(*  Title:      Tools/Code/code_printer.ML
    Author:     Florian Haftmann, TU Muenchen

Generic operations for pretty printing of target language code.
*)


signature CODE_PRINTER =
sig
  type itype = Code_Thingol.itype
  type iterm = Code_Thingol.iterm
  type const = Code_Thingol.const
  type dict = Code_Thingol.dict

  val eqn_error: theory -> thm option -> string -> 'a

  val @@ : 'a * 'a -> 'a list
  val @| : 'a list * 'a -> 'a list
  val str: string -> Pretty.T
  val concat: Pretty.T list -> Pretty.T
  val brackets: Pretty.T list -> Pretty.T
  val enclose: string -> string -> Pretty.T list -> Pretty.T
  val commas: Pretty.T list -> Pretty.T list
  val enum: string -> string -> string -> Pretty.T list -> Pretty.T
  val enum_default: string -> string -> string -> string -> Pretty.T list -> Pretty.T
  val semicolon: Pretty.T list -> Pretty.T
  val doublesemicolon: Pretty.T list -> Pretty.T
  val indent: int -> Pretty.T -> Pretty.T
  val markup_stmt: Code_Symbol.T -> Pretty.T -> Pretty.T
  val format: Code_Symbol.T list -> int -> Pretty.T -> string

  type var_ctxt
  val make_vars: string list -> var_ctxt
  val intro_vars: string list -> var_ctxt -> var_ctxt
  val lookup_var: var_ctxt -> string -> string
  val intro_base_names: (string -> bool) -> (string -> string)
    -> string list -> var_ctxt -> var_ctxt
  val intro_base_names_for: (string -> bool) -> (Code_Symbol.T -> string)
    -> iterm list -> var_ctxt -> var_ctxt
  val aux_params: var_ctxt -> iterm list list -> string list

  type literals
  val Literals: { literal_string: string -> string,
        literal_numeral: int -> string,
        literal_list: Pretty.T list -> Pretty.T, infix_cons: int * string }
    -> literals
  val literal_string: literals -> string -> string
  val literal_numeral: literals -> int -> string
  val literal_list: literals -> Pretty.T list -> Pretty.T
  val infix_cons: literals -> int * string

  type lrx
  val L: lrx
  val R: lrx
  val X: lrx
  type fixity
  val BR: fixity
  val NOBR: fixity
  val INFX: int * lrx -> fixity
  val APP: fixity
  val brackify: fixity -> Pretty.T list -> Pretty.T
  val brackify_infix: int * lrx -> fixity -> Pretty.T * Pretty.T * Pretty.T -> Pretty.T
  val brackify_block: fixity -> Pretty.T -> Pretty.T list -> Pretty.T -> Pretty.T
  val gen_applify: bool -> string -> string -> ('a -> Pretty.T) -> fixity -> Pretty.T -> 'list -> Pretty.T
  val applify: string -> string -> ('a -> Pretty.T) -> fixity -> Pretty.T -> 'list -> Pretty.T
  val tuplify: (fixity -> 'a -> Pretty.T) -> fixity -> 'list -> Pretty.T option

  type raw_const_syntax
  val plain_const_syntax: string -> raw_const_syntax
  type simple_const_syntax
  val simple_const_syntax: simple_const_syntax -> raw_const_syntax
  type complex_const_syntax
  val complex_const_syntax: complex_const_syntax -> raw_const_syntax
  val parse_const_syntax: raw_const_syntax parser
  val requires_args: raw_const_syntax -> int
  datatype const_printer = Plain_printer of string
    | Complex_printer of (var_ctxt -> fixity -> iterm -> Pretty.T)
        -> thm option -> var_ctxt -> fixity -> (iterm * itype) list -> Pretty.T
  type const_syntax = int * const_printer
  val prep_const_syntax: theory -> literals
    -> string -> raw_const_syntax -> const_syntax
  type tyco_syntax
  val parse_tyco_syntax: tyco_syntax parser
  val gen_print_app: (thm option -> var_ctxt -> const * iterm list -> Pretty.T list)
    -> (thm option -> var_ctxt -> fixity -> iterm -> Pretty.T)
    -> (string -> const_syntax option)
    -> thm option -> var_ctxt -> fixity -> const * iterm list -> Pretty.T
  val gen_print_bind: (thm option -> var_ctxt -> fixity -> iterm -> Pretty.T)
    -> thm option -> fixity
    -> iterm -> var_ctxt -> Pretty.T * var_ctxt

  type identifiers
  type printings
  type data
  val empty_data: data
  val map_data: (string list * identifiers * printings
    -> string list * identifiers * printings)
    -> data -> data
  val merge_data: data * data -> data
  val the_reserved: data -> string list;
  val the_identifiers: data -> identifiers;
  val the_printings: data -> printings;
end;

structure Code_Printer : CODE_PRINTER =
struct

open Basic_Code_Symbol;
open Code_Thingol;

(** generic nonsense *)

fun eqn_error thy (SOME thm) s =
      error (s ^ ",\nin equation " ^ Thm.string_of_thm_global thy thm)
  | eqn_error _ NONE s = error s;

val code_presentationN = "code_presentation";
val stmt_nameN = "stmt_name";
val _ = Markup.add_mode code_presentationN YXML.output_markup;


(** assembling and printing text pieces **)

infixr 5 @@;
infixr 5 @|;
fun x @@ y = [x, y];
fun xs @| y = xs @ [y];
fun with_no_print_mode f = Print_Mode.setmp [] f;
val str = with_no_print_mode Pretty.str;
val concat = Pretty.block o Pretty.breaks;
val commas = with_no_print_mode Pretty.commas;
fun enclose l r = with_no_print_mode (Pretty.enclose l r);
val brackets = enclose "(" ")" o Pretty.breaks;
fun enum sep l r = with_no_print_mode (Pretty.enum sep l r);
fun enum_default default sep l r [] = str default
  | enum_default default sep l r xs = enum sep l r xs;
fun semicolon ps = Pretty.block [concat ps, str ";"];
fun doublesemicolon ps = Pretty.block [concat ps, str ";;"];
fun indent i = with_no_print_mode (Pretty.indent i);

fun with_presentation_marker f = Print_Mode.setmp [code_presentationN] f;

fun markup_stmt sym = with_presentation_marker
  (Pretty.mark (code_presentationN, [(stmt_nameN, Code_Symbol.marker sym)]));

fun filter_presentation [] tree =
      Buffer.empty
      |> fold XML.add_content tree
  | filter_presentation presentation_syms tree =
      let
        val presentation_idents = map Code_Symbol.marker presentation_syms
        fun is_selected (name, attrs) =
          name = code_presentationN
          andalso member (op =) presentation_idents (the (Properties.get attrs stmt_nameN));
        fun add_content_with_space tree (is_first, buf) =
          buf
          |> not is_first ? Buffer.add "\n\n"
          |> XML.add_content tree
          |> pair false;
        fun filter (XML.Elem (name_attrs, xs)) =
              fold (if is_selected name_attrs then add_content_with_space else filter) xs
          | filter (XML.Text _) = I;
      in snd (fold filter tree (true, Buffer.empty)) end;

fun format presentation_names width =
  with_presentation_marker (Pretty.string_of_margin width)
  #> YXML.parse_body
  #> filter_presentation presentation_names
  #> Buffer.add "\n"
  #> Buffer.content;


(** names and variable name contexts **)

type var_ctxt = string Symtab.table * Name.context;

fun make_vars names = (fold (fn name => Symtab.update_new (name, name)) names Symtab.empty,
  Name.make_context names);

fun intro_vars names (namemap, namectxt) =
  let
    val (names', namectxt') = fold_map Name.variant names namectxt;
    val namemap' = fold2 (curry Symtab.update) names names' namemap;
  in (namemap', namectxt'end;

fun lookup_var (namemap, _) name =
  case Symtab.lookup namemap name of
    SOME name' => name'
  | NONE => error ("Invalid name in context: " ^ quote name);

fun aux_params vars lhss =
  let
    fun fish_param _ (w as SOME _) = w
      | fish_param (IVar (SOME v)) NONE = SOME v
      | fish_param _ NONE = NONE;
    fun fillup_param _ (_, SOME v) = v
      | fillup_param x (i, NONE) = x ^ string_of_int i;
    val fished1 = fold (map2 fish_param) lhss (replicate (length (hd lhss)) NONE);
    val x = singleton (Name.variant_list (map_filter I fished1)) "x";
    val fished2 = map_index (fillup_param x) fished1;
    val (fished3, _) = fold_map Name.variant fished2 Name.context;
    val vars' = intro_vars fished3 vars;
  in map (lookup_var vars') fished3 end;

fun intro_base_names no_syntax deresolve =
  map_filter (fn name => if no_syntax name then
      let val name' = deresolve name in
        if Long_Name.is_qualified name' then NONE else SOME name'
      end else NONE)
  #> intro_vars;

fun intro_base_names_for no_syntax deresolve ts =
  []
  |> fold Code_Thingol.add_constsyms ts 
  |> intro_base_names (fn Constant const => no_syntax const | _ => true) deresolve;


(** pretty literals **)

datatype literals = Literals of {
  literal_string: string -> string,
  literal_numeral: int -> string,
  literal_list: Pretty.T list -> Pretty.T,
  infix_cons: int * string
};

fun dest_Literals (Literals lits) = lits;

val literal_string = #literal_string o dest_Literals;
val literal_numeral = #literal_numeral o dest_Literals;
val literal_list = #literal_list o dest_Literals;
val infix_cons = #infix_cons o dest_Literals;


(** syntax printer **)

(* binding priorities *)

datatype lrx = L | R | X;

datatype fixity =
    BR
  | NOBR
  | INFX of (int * lrx);

val APP = INFX (~1, L);

fun fixity_lrx L L = false
  | fixity_lrx R R = false
  | fixity_lrx _ _ = true;

fun fixity NOBR _ = false
  | fixity _ NOBR = false
  | fixity (INFX (pr, lr)) (INFX (pr_ctxt, lr_ctxt)) =
      pr < pr_ctxt
      orelse pr = pr_ctxt
        andalso fixity_lrx lr lr_ctxt
      orelse pr_ctxt = ~1
  | fixity BR (INFX _) = false
  | fixity _ _ = true;

fun gen_brackify _ [p] = p
  | gen_brackify true (ps as _::_) = enclose "(" ")" ps
  | gen_brackify false (ps as _::_) = Pretty.block ps;

fun brackify fxy_ctxt =
  gen_brackify (fixity BR fxy_ctxt) o Pretty.breaks;

fun brackify_infix infx fxy_ctxt (l, m, r) =
  gen_brackify (fixity (INFX infx) fxy_ctxt) [l, str " ", m, Pretty.brk 1, r];

fun brackify_block fxy_ctxt p1 ps p2 =
  let val p = Pretty.block_enclose (p1, p2) ps
  in if fixity BR fxy_ctxt
    then enclose "(" ")" [p]
    else p
  end;

fun gen_applify strict opn cls f fxy_ctxt p [] =
      if strict
      then gen_brackify (fixity BR fxy_ctxt) [p, str (opn ^ cls)]
      else p
  | gen_applify strict opn cls f fxy_ctxt p ps =
      gen_brackify (fixity BR fxy_ctxt) (p @@ enum "," opn cls (map f ps));

fun applify opn = gen_applify false opn;

fun tuplify _ _ [] = NONE
  | tuplify print fxy [x] = SOME (print fxy x)
  | tuplify print _ xs = SOME (enum "," "(" ")" (map (print NOBR) xs));


(* generic syntax *)

type simple_const_syntax = int * ((fixity -> iterm -> Pretty.T)
  -> fixity -> (iterm * itype) list -> Pretty.T);

type complex_const_syntax = int * (literals
  -> (var_ctxt -> fixity -> iterm -> Pretty.T)
    -> thm option -> var_ctxt -> fixity -> (iterm * itype) list -> Pretty.T);

datatype raw_const_syntax = plain_const_syntax of string
  | complex_const_syntax of complex_const_syntax;

fun simple_const_syntax syn =
  complex_const_syntax
    (apsnd (fn f => fn _ => fn print => fn _ => fn vars => f (print vars)) syn);

fun requires_args (plain_const_syntax _) = 0
  | requires_args (complex_const_syntax (k, _)) = k;

datatype const_printer = Plain_printer of string
  | Complex_printer of (var_ctxt -> fixity -> iterm -> Pretty.T)
      -> thm option -> var_ctxt -> fixity -> (iterm * itype) list -> Pretty.T;

type const_syntax = int * const_printer;

fun prep_const_syntax thy literals c (plain_const_syntax s) =
      (Code.args_number thy c, Plain_printer s)
  | prep_const_syntax thy literals c (complex_const_syntax (n, f))=
      (n, Complex_printer (f literals));

fun gen_print_app print_app_expr print_term const_syntax some_thm vars fxy
    (app as ({ sym, dom, ... }, ts)) =
  case sym of
    Constant const => (case const_syntax const of
      NONE => brackify fxy (print_app_expr some_thm vars app)
    | SOME (_, Plain_printer s) =>
        brackify fxy (str s :: map (print_term some_thm vars BR) ts)
    | SOME (k, Complex_printer print) =>
        let
          fun print' fxy ts =
            print (print_term some_thm) some_thm vars fxy (ts ~~ take k dom);
        in
          if k = length ts
          then print' fxy ts
          else if k < length ts
          then case chop k ts of (ts1, ts2) =>
            brackify fxy (print' APP ts1 :: map (print_term some_thm vars BR) ts2)
          else print_term some_thm vars fxy (Code_Thingol.eta_expand k app)
        end)
  | _ => brackify fxy (print_app_expr some_thm vars app);

fun gen_print_bind print_term thm (fxy : fixity) pat vars =
  let
    val vs = Code_Thingol.fold_varnames (insert (op =)) pat [];
    val vars' = intro_vars vs vars;
  in (print_term thm vars' fxy pat, vars'end;

type tyco_syntax = int * ((fixity -> itype -> Pretty.T)
  -> fixity -> itype list -> Pretty.T);


(* mixfix syntax *)

datatype 'a mixfix =
    Arg of fixity
  | String of string
  | Break;

fun printer_of_mixfix prep_arg (fixity_this, mfx) =
  let
    fun is_arg (Arg _) = true
      | is_arg _ = false;
    val i = (length o filter is_arg) mfx;
    fun fillin _ [] [] =
          []
      | fillin print (Arg fxy :: mfx) (a :: args) =
          (print fxy o prep_arg) a :: fillin print mfx args
      | fillin print (String s :: mfx) args =
          str s :: fillin print mfx args
      | fillin print (Break :: mfx) args =
          Pretty.brk 1 :: fillin print mfx args;
  in
    (i, fn print => fn fixity_ctxt => fn args =>
      gen_brackify (fixity fixity_this fixity_ctxt) (fillin print mfx args))
  end;

fun read_infix (fixity_this, i) s =
  let
    val l = case fixity_this of L => INFX (i, L) | _ => INFX (i, X);
    val r = case fixity_this of R => INFX (i, R) | _ => INFX (i, X);
  in
    (INFX (i, fixity_this), [Arg l, String " "String s, Break, Arg r])
  end;

fun read_mixfix s =
  let
    val sym_any = Scan.one Symbol.not_eof;
    val parse = Scan.optional ($$ "!" >> K NOBR) BR -- Scan.repeat (
         ($$ "(" -- $$ "_" -- $$ ")" >> K (Arg NOBR))
      || ($$ "_" >> K (Arg BR))
      || ($$ "/" |-- Scan.repeat ($$ " ") >> (K Break))
      || (Scan.repeat1
           (   $$ "'" |-- sym_any
            || Scan.unless ($$ "_" || $$ "/" || $$ "(" |-- $$ "_" |-- $$ ")")
                 sym_any) >> (String o implode)));
    fun err s (_, NONE) = (fn () => "malformed mixfix annotation: " ^ quote s)
      | err _ (_, SOME msg) = msg;
  in
    case Scan.finite Symbol.stopper parse (Symbol.explode s) of
        (fixity_mixfix, []) => fixity_mixfix
      | _ => Scan.!! (err s) Scan.fail ()
  end;

val parse_fixity =
  (\<^keyword>\<open>infix\<close> >> K X) || (\<^keyword>\<open>infixl\<close> >> K L) || (\<^keyword>\<open>infixr\<close> >> K R)

fun parse_mixfix x =
  (Parse.string >> read_mixfix
  || parse_fixity -- Parse.nat -- Parse.string
     >> (fn ((fixity, i), s) => read_infix (fixity, i) s)) x;

fun syntax_of_mixfix of_plain of_printer prep_arg (BR, [String s]) = of_plain s
  | syntax_of_mixfix of_plain of_printer prep_arg (fixity, mfx) =
      of_printer (printer_of_mixfix prep_arg (fixity, mfx));

fun parse_tyco_syntax x =
  (parse_mixfix >> syntax_of_mixfix (fn s => (0, (K o K o K o str) s)) I I) x;

val parse_const_syntax =
  parse_mixfix >> syntax_of_mixfix plain_const_syntax simple_const_syntax fst;


(** custom data structure **)

type identifiers = (string list * stringstring list * stringstring list * stringstring list * string,
  string list * stringstring list * string) Code_Symbol.data;
type printings = (const_syntax, tyco_syntax, string, unit, unit,
    (Pretty.T * Code_Symbol.T list)) Code_Symbol.data;

datatype data = Data of { reserved: string list, identifiers: identifiers,
  printings: printings };

fun make_data (reserved, identifiers, printings) =
  Data { reserved = reserved, identifiers = identifiers, printings = printings };
val empty_data = make_data ([], Code_Symbol.empty_data, Code_Symbol.empty_data);
fun map_data f (Data { reserved, identifiers, printings }) =
  make_data (f (reserved, identifiers, printings));
fun merge_data (Data { reserved = reserved1, identifiers = identifiers1, printings = printings1 },
    Data { reserved = reserved2, identifiers = identifiers2, printings = printings2 }) =
  make_data (merge (op =) (reserved1, reserved2),
    Code_Symbol.merge_data (identifiers1, identifiers2), Code_Symbol.merge_data (printings1, printings2));

fun the_reserved (Data { reserved, ... }) = reserved;
fun the_identifiers (Data { identifiers , ... }) = identifiers;
fun the_printings (Data { printings, ... }) = printings;


end(*struct*)

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤





Download des
Quellennavigators
Download des
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff



                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik