thys2/Term_pat.thy
author Christian Urban <christian dot urban at kcl dot ac dot uk>
Sat, 13 Sep 2014 04:39:07 +0100
changeset 26 1cde7bf45858
parent 25 a5f5b9336007
permissions -rw-r--r--
deleted *~ files

theory Term_pat
imports Main
begin

text {*
  @{text "trace_match"} is the flag to control the tracing of matching activities.
*}

ML {*
  val trace_match = Attrib.setup_config_bool @{binding trace_match} (K false)
*}

section {* Monad with support of excepion *}

ML {*

structure Exceptional = 
struct
  datatype ('a, 'b) Exceptional = 
        Exception of 'a | Success of 'b
  fun (scan1 :|-- scan2) st = 
     case scan1 st of
       Success (v, st') => scan2 v st'
     | Exception e => Exception e
  fun returnM v = (fn st => Success (v, st))
  fun (scan1 |-- scan2) = scan1 :|-- (K scan2)
  fun (scan1 -- scan2) = scan1 :|--  (fn v1 => scan2 :|-- (fn v2 => returnM (v1, v2)))
  fun liftE scan st = let
      val (v, st') = scan st 
  in Success (v, st') end
  fun getM y = Success (y, y)
  fun setM v = (fn _ => Success (v, v))
  fun failM x = (fn _ =>  raise (Scan.fail x))
  fun m0M f = getM :|-- f
  fun pushM x = (m0M (fn (top::rest) => setM (top::top::rest) |-- returnM top)) x
  fun popM x = (m0M (fn (top::rest) => setM rest  |-- returnM top)) x
  (* [f] is assumed to be a monad valued function, so that it can be constructed using monad combinators.
     For this reason, [f] is assumed to take two arguments.
   *)
  fun topM f = m0M (fn (top::rest) => 
                 case f top top of
                   Success (v, top') => (setM (top'::rest) |-- returnM v)
                 | Exception e => (K (Exception e)))
 (* all the [f] in the following are monad or moand function on stack element (not on stack itself )*)
  (* [f] in the following is assumed to be plain monad on stack element, not a monad valued function *)
  fun liftM f = topM (K f)
  (* [f] in the following is a monad valued funtion depending only on the first component *)
  fun m1M f = m0M (fn (st1, st2) => f st1)
  (* [f] in the following is a monad valued funtion depending only on the second component *)
  fun m2M f = m0M (fn (st1, st2) => f st2)
  fun localM f = pushM |-- f :|-- (fn res => popM |-- returnM res)
  fun s1M n1 = m0M (fn (_, st2) => setM (n1, st2))
  fun s2M n2 = m0M (fn (st1, _)  => setM (st1, n2))
  (* The flowing primed version is meant to substitute the unprimed version *)
  fun m0M' f = liftM (m0M f)
  fun m1M' f = liftM (m1M f)
  fun m2M' f = liftM (m2M f)
  fun lift scan = (fn (d, a) =>
      case scan a of
        Success (v, b) => Success (v, (d, b))
      | Exception e => Exception e
  )
  fun normVal (Success v) = v
  fun normExcp (Exception e) = e
  fun (scan >> f) = scan :|-- (fn v => returnM (f v))
  fun raiseM v = K (Exception v)
end
*}

(* ccc *)

section {* State monad with stack *}

ML {*
structure StackMonad = struct
  (* getM fetches the underlying state *)
  fun getM y = (y, y)
  (* setM sets the underlying state *)
  fun setM v = (fn _ => (v, v))
  (* returnM retruns any value *)
  fun returnM v = (fn st => (v, st))
  (* failM failes the current process *)
  fun failM x = (fn _ =>  raise (Scan.fail x))
  (* [m0M f] applies function f to the underlying state *)
  fun m0M f = getM :|-- f
  fun pushM x = (m0M (fn (top::rest) => setM (top::top::rest) |-- returnM top)) x
  fun popM x = (m0M (fn (top::rest) => setM rest  |-- returnM top)) x
  (* [f] is assumed to be a monad valued function, so that it can be constructed using monad combinators.
     For this reason, [f] is assumed to take two arguments.
   *)
  fun topM f = m0M (fn (top::rest) => let val (v, top') = f top top in 
                                          setM (top'::rest) |-- returnM v
                                      end)
  (* all the [f] in the following are monad or moand function on stack element (not on stack itself )*)
  (* [f] in the following is assumed to be plain monad on stack element, not a monad valued function *)
  fun liftM f = topM (K f)
  (* [f] in the following is a monad valued funtion depending only on the first component *)
  fun m1M f = m0M (fn (st1, st2) => f st1)
  (* [f] in the following is a monad valued funtion depending only on the second component *)
  fun m2M f = m0M (fn (st1, st2) => f st2)
  fun localM f = pushM |-- f :|-- (fn res => popM |-- returnM res)
  fun s1M n1 = m0M (fn (_, st2) => setM (n1, st2))
  fun s2M n2 = m0M (fn (st1, _)  => setM (st1, n2))
  fun dgM scan arg = let val (v, [arg']) = scan [arg] in (v, arg') end
  (* The flowing primed version is meant to substitute the unprimed version *)
  fun m0M' f = liftM (m0M f)
  fun m1M' f = liftM (m1M f)
  fun m2M' f = liftM (m2M f)
  val liftE = I
  val lift = Scan.lift
  val :|--  = Scan.:|--
  val |--  = Scan.|--
  val --  = Scan.--
  val >> = Scan.>>
  val normVal = I
end
*}

ML {*
  open StackMonad
  open Exceptional 
*}

section {* State monad with stack *}

ML {*
local
  val tracing  = (fn ctxt => fn str =>
                   if (Config.get ctxt trace_match) then tracing str else ())
  fun string_of_term ctxt t = t |> Syntax.pretty_term ctxt |> Pretty.str_of
  fun pterm ctxt t =
          t |> string_of_term ctxt |> tracing ctxt
in
  fun tracingM s =  liftM (m2M (fn ctxt => returnM (tracing ctxt s)))
  fun ptermM t = liftM (m2M (fn ctxt => returnM (pterm ctxt t)))
  fun presultM tag scan = scan :|-- (fn res => 
                                     tracingM tag |--
                                     ptermM res |--
                                     returnM res
                                   )
end
*}

ML {*
local
  val tracing  = (fn ctxt => fn str =>
                   if (Config.get ctxt trace_match) then tracing str else ())
  fun string_of_term ctxt t = t |> Syntax.pretty_term ctxt |> Pretty.str_of
  fun pterm ctxt t =
          t |> string_of_term ctxt |> tracing ctxt
  fun match_fun1 pat term (st, ctxt) = let
     val _ = tracing ctxt "match_fun on:"
     val _ = tracing ctxt pat
     val _ = pterm ctxt term
  in
             (Proof_Context.match_bind_i true 
                       [([Proof_Context.read_term_pattern ctxt pat], term)] ctxt |>
              (fn (_, ctxt) => (term, (st, ctxt)))) 
                 handle (ERROR x)         =>  
                          raise (Scan.fail x) 
  end
in
  fun match_fun pat term = liftE (match_fun1 pat term)
end
*}

ML {*
  fun err_trans (ERROR x) = raise (Scan.fail x)
    | err_trans e = e
*}

ML {*
  fun exnM f monad = (fn inp => monad inp handle e => raise (f e))
*}

ML {*
  fun match_fun pat term = 
   tracingM "match_fun on:" |--
   tracingM pat  |--
   ptermM term |--
   liftM (lift (m0M (fn ctxt => (* setM (Variable.auto_fixes term ctxt) |-- *)
    (liftE (Proof_Context.match_bind_i true  [([Proof_Context.read_term_pattern ctxt pat], term)])) |--
    returnM term
   )) |> exnM err_trans)
*}

ML {*
local 
  val >> = Scan.>>
in
  val match_parser = 
     (Args.name_source) >> (fn s => "(match_fun "^ML_Syntax.print_string s^")")
end
*}

ML {*
local 
  val  >> = Scan.>>
in
  val fterm_parser = 
       Args.name_source >>
      (fn term => "liftM (exnM err_trans (lift (m0M (fn ctxt => returnM ((Syntax.read_term ctxt) "^ML_Syntax.print_string term ^")))))")
end
*}

setup {*
  ML_Antiquote.inline @{binding match} (Scan.lift match_parser) #>
  ML_Antiquote.inline @{binding fterm} (Scan.lift fterm_parser)
*}

ML {*
  infixr 0 |||
  fun (scan1 ||| scan2) xs = scan1 xs handle _ => scan2 xs
*}

declare [[trace_match = false]]

ML {*
  val t = [((), @{context})] |> 
          (@{match "(?x::nat) + ?y"} @{term "(1::nat) + 2"} |--
           @{fterm "?x"})
*}


ML {* (* testings and examples *)
  fun trans t = (@{match "(?x ::nat) + ?y"} t |--
                (@{fterm "?x"} :|-- trans) :|-- @{match "?u"} |--
                (@{fterm "?y"} :|-- trans) :|-- @{match "?v"} |--
                @{fterm "?v * ?v * ?u"}
                          ||
                @{match "(?x ::nat) - ?y"} t |--
                (@{fterm "?x"} :|-- trans) :|-- @{match "?u"} |--
                (@{fterm "?y"} :|-- trans) :|-- @{match "v"} |--
                @{fterm "?v - ?v * ?u"}
                          ||              
                (returnM t))
*}

ML {*
  val t = trans @{term "(u - (x::nat) + y)"} [((), @{context})] |> normVal |>
    apfst (cterm_of @{theory}) |> fst
  *}

end