src/Pure/Syntax/source.ML
changeset 4954 cf1404c3f7bb
parent 4946 d8e5c6e31854
child 4960 e07823c1ebff
equal deleted inserted replaced
4953:78ff4a45a822 4954:cf1404c3f7bb
     1 (*  Title:      Isar/source.ML
     1 (*  Title:      Pure/Syntax/source.ML
     2     ID:         $Id$
     2     ID:         $Id$
     3     Author:     Markus Wenzel, TU Muenchen
     3     Author:     Markus Wenzel, TU Muenchen
     4 
     4 
     5 Co-algebraic data sources.
     5 Co-algebraic data sources.
     6 *)
     6 *)
     9 sig
     9 sig
    10   type ('a, 'b) source
    10   type ('a, 'b) source
    11   val set_prompt: string -> ('a, 'b) source -> ('a, 'b) source
    11   val set_prompt: string -> ('a, 'b) source -> ('a, 'b) source
    12   val get: ('a, 'b) source -> 'a list * ('a, 'b) source
    12   val get: ('a, 'b) source -> 'a list * ('a, 'b) source
    13   val unget: 'a list * ('a, 'b) source -> ('a, 'b) source
    13   val unget: 'a list * ('a, 'b) source -> ('a, 'b) source
    14   val get_single: ('a, 'b) source -> 'a * ('a, 'b) source
    14   val get_single: ('a, 'b) source -> 'a option * ('a, 'b) source
    15   val exhaust: ('a, 'b) source -> 'a list
    15   val exhaust: ('a, 'b) source -> 'a list
    16   val filter: ('a -> bool) -> ('a, 'b) source -> ('a, ('a, 'b) source) source
    16   val filter: ('a -> bool) -> ('a, 'b) source -> ('a, ('a, 'b) source) source
    17   val of_list: 'a list -> ('a, 'a list) source
    17   val of_list: 'a list -> ('a, 'a list) source
    18   val of_string: string -> (string, string list) source
    18   val of_string: string -> (string, string list) source
    19   val of_stream: TextIO.instream -> TextIO.outstream -> (string, unit) source
    19   val of_stream: TextIO.instream -> TextIO.outstream -> (string, unit) source
    33 
    33 
    34 datatype ('a, 'b) source =
    34 datatype ('a, 'b) source =
    35   Source of
    35   Source of
    36    {buffer: 'a list,
    36    {buffer: 'a list,
    37     info: 'b,
    37     info: 'b,
    38     prompt: string option,
    38     prompt: string,
    39     drain: string -> 'b -> 'a list * 'b};
    39     drain: string -> 'b -> 'a list * 'b};
    40 
    40 
    41 fun make_source buffer info prompt drain =
    41 fun make_source buffer info prompt drain =
    42   Source {buffer = buffer, info = info, prompt = prompt, drain = drain};
    42   Source {buffer = buffer, info = info, prompt = prompt, drain = drain};
    43 
    43 
    45 (* prompt *)
    45 (* prompt *)
    46 
    46 
    47 val default_prompt = "> ";
    47 val default_prompt = "> ";
    48 
    48 
    49 fun set_prompt prompt (Source {buffer, info, prompt = _, drain}) =
    49 fun set_prompt prompt (Source {buffer, info, prompt = _, drain}) =
    50   make_source buffer info (Some prompt) drain;
    50   make_source buffer info prompt drain;
    51 
    51 
    52 
    52 
    53 (* get / unget *)
    53 (* get / unget *)
    54 
    54 
    55 fun get (Source {buffer = [], info, prompt, drain}) =
    55 fun get (Source {buffer = [], info, prompt, drain}) =
    56       let val (xs, info') = drain (if_none prompt default_prompt) info
    56       let val (xs, info') = drain prompt info
    57       in (xs, make_source [] info' prompt drain) end
    57       in (xs, make_source [] info' prompt drain) end
    58   | get (Source {buffer, info, prompt, drain}) =
    58   | get (Source {buffer, info, prompt, drain}) =
    59       (buffer, make_source [] info prompt drain);
    59       (buffer, make_source [] info prompt drain);
    60 
    60 
    61 fun unget (xs, Source {buffer, info, prompt, drain}) =
    61 fun unget (xs, Source {buffer, info, prompt, drain}) =
    66 
    66 
    67 fun get_prompt prompt src = get (set_prompt prompt src);
    67 fun get_prompt prompt src = get (set_prompt prompt src);
    68 
    68 
    69 fun get_single src =
    69 fun get_single src =
    70   (case get src of
    70   (case get src of
    71     ([], _) => error "Input source exhausted!"
    71     ([], src') => (None, src')
    72   | (x :: xs, src') => (x, unget (xs, src')));
    72   | (x :: xs, src') => (Some x, unget (xs, src')));
    73 
    73 
    74 fun exhaust src =
    74 fun exhaust src =
    75   (case get src of
    75   (case get src of
    76     ([], _) => []
    76     ([], _) => []
    77   | (xs, src') => xs @ exhaust src');
    77   | (xs, src') => xs @ exhaust src');
    87     if null xs then (xs, src')
    87     if null xs then (xs, src')
    88     else if null xs' then drain_filter pred prompt src'
    88     else if null xs' then drain_filter pred prompt src'
    89     else (xs', src')
    89     else (xs', src')
    90   end;
    90   end;
    91 
    91 
    92 fun filter pred src = make_source [] src None (drain_filter pred);
    92 fun filter pred src = make_source [] src default_prompt (drain_filter pred);
    93 
    93 
    94 
    94 
    95 
    95 
    96 (** build sources **)
    96 (** build sources **)
    97 
    97 
    98 (* list source *)
    98 (* list source *)
    99 
    99 
   100 (*limiting the master input buffer considerably improves performance*)
   100 (*limiting the input buffer considerably improves performance*)
   101 val limit = 4000;
   101 val limit = 4000;
   102 
   102 
   103 fun drain_list _ xs = (take (limit, xs), drop (limit, xs));
   103 fun drain_list _ xs = (take (limit, xs), drop (limit, xs));
   104 
   104 
   105 fun of_list xs = make_source [] xs None drain_list;
   105 fun of_list xs = make_source [] xs default_prompt drain_list;
   106 fun of_string str = of_list (explode str);
   106 val of_string = of_list o explode;
   107 
   107 
   108 
   108 
   109 (* stream source *)
   109 (* stream source *)
   110 
   110 
   111 fun drain_stream instream outstream prompt () =
   111 fun drain_stream instream outstream prompt () =
   112   (TextIO.output (outstream, prompt);
   112   (TextIO.output (outstream, prompt);
   113     TextIO.flushOut outstream;
   113     TextIO.flushOut outstream;
   114     (explode (TextIO.inputLine instream), ()));
   114     (explode (TextIO.inputLine instream), ()));
   115 
   115 
   116 fun of_stream instream outstream =
   116 fun of_stream instream outstream =
   117   make_source [] () None (drain_stream instream outstream);
   117   make_source [] () default_prompt (drain_stream instream outstream);
   118 
   118 
   119 val tty = of_stream TextIO.stdIn TextIO.stdOut;
   119 val tty = of_stream TextIO.stdIn TextIO.stdOut;
   120 
   120 
   121 
   121 
   122 
   122 
   123 (** compose sources **)
   123 (** compose sources **)
   124 
   124 
   125 (* make state-based *)
   125 fun drain_source source stopper scan prompt src =
       
   126   source prompt get_prompt unget stopper scan src;
   126 
   127 
   127 fun drain_state_source stopper scan prompt state_src =
   128 
   128   Scan.source prompt get_prompt unget stopper scan state_src;
   129 (* state-based *)
   129 
   130 
   130 fun state_source init_state stopper scan src =
   131 fun state_source init_state stopper scan src =
   131   make_source [] (init_state, src) None (drain_state_source stopper scan);
   132   make_source [] (init_state, src) default_prompt (drain_source Scan.source' stopper scan);
   132 
   133 
   133 
   134 
   134 (* not state-based *)
   135 (* non state-based *)
   135 
       
   136 fun drain_source stopper scan prompt src =
       
   137   apsnd snd (Scan.source prompt get_prompt unget stopper (Scan.lift scan) ((), src));
       
   138 
   136 
   139 fun source stopper scan src =
   137 fun source stopper scan src =
   140    make_source [] src None (drain_source stopper scan);
   138    make_source [] src default_prompt (drain_source Scan.source stopper scan);
   141 
   139 
   142 
   140 
   143 
   141 
   144 (** test source interactively **)
   142 (** test source interactively **)
   145 
   143