src/HOL/List.thy
changeset 68362 27237ee2e889
parent 68325 57e4bd1e2e18
child 68527 2f4e2aab190a
--- a/src/HOL/List.thy	Sat Jun 02 22:40:03 2018 +0200
+++ b/src/HOL/List.thy	Sun Jun 03 18:23:29 2018 +0200
@@ -433,75 +433,70 @@
 syntax (ASCII)
   "_lc_gen" :: "'a \<Rightarrow> 'a list \<Rightarrow> lc_qual"  ("_ <- _")
 
-(* These are easier than ML code but cannot express the optimized
-   translation of [e. p<-xs]
-translations
-  "[e. p<-xs]" => "concat(map (_lc_abs p [e]) xs)"
-  "_listcompr e (_lc_gen p xs) (_lc_quals Q Qs)"
-   => "concat (map (_lc_abs p (_listcompr e Q Qs)) xs)"
-  "[e. P]" => "if P then [e] else []"
-  "_listcompr e (_lc_test P) (_lc_quals Q Qs)"
-   => "if P then (_listcompr e Q Qs) else []"
-  "_listcompr e (_lc_let b) (_lc_quals Q Qs)"
-   => "_Let b (_listcompr e Q Qs)"
-*)
-
 parse_translation \<open>
-  let
-    val NilC = Syntax.const @{const_syntax Nil};
-    val ConsC = Syntax.const @{const_syntax Cons};
-    val mapC = Syntax.const @{const_syntax map};
-    val concatC = Syntax.const @{const_syntax concat};
-    val IfC = Syntax.const @{const_syntax If};
-
-    fun single x = ConsC $ x $ NilC;
-
-    fun pat_tr ctxt p e opti = (* %x. case x of p => e | _ => [] *)
-      let
-        (* FIXME proper name context!? *)
-        val x =
-          Free (singleton (Name.variant_list (fold Term.add_free_names [p, e] [])) "x", dummyT);
-        val e = if opti then single e else e;
-        val case1 = Syntax.const @{syntax_const "_case1"} $ p $ e;
-        val case2 =
-          Syntax.const @{syntax_const "_case1"} $
-            Syntax.const @{const_syntax Pure.dummy_pattern} $ NilC;
-        val cs = Syntax.const @{syntax_const "_case2"} $ case1 $ case2;
-      in Syntax_Trans.abs_tr [x, Case_Translation.case_tr false ctxt [x, cs]] end;
-
-    fun abs_tr ctxt p e opti =
-      (case Term_Position.strip_positions p of
-        Free (s, T) =>
-          let
-            val thy = Proof_Context.theory_of ctxt;
-            val s' = Proof_Context.intern_const ctxt s;
-          in
-            if Sign.declared_const thy s'
-            then (pat_tr ctxt p e opti, false)
-            else (Syntax_Trans.abs_tr [p, e], true)
-          end
-      | _ => (pat_tr ctxt p e opti, false));
-
-    fun lc_tr ctxt [e, Const (@{syntax_const "_lc_test"}, _) $ b, qs] =
-          let
-            val res =
-              (case qs of
-                Const (@{syntax_const "_lc_end"}, _) => single e
-              | Const (@{syntax_const "_lc_quals"}, _) $ q $ qs => lc_tr ctxt [e, q, qs]);
-          in IfC $ b $ res $ NilC end
-      | lc_tr ctxt
-            [e, Const (@{syntax_const "_lc_gen"}, _) $ p $ es,
-              Const(@{syntax_const "_lc_end"}, _)] =
-          (case abs_tr ctxt p e true of
-            (f, true) => mapC $ f $ es
-          | (f, false) => concatC $ (mapC $ f $ es))
-      | lc_tr ctxt
-            [e, Const (@{syntax_const "_lc_gen"}, _) $ p $ es,
-              Const (@{syntax_const "_lc_quals"}, _) $ q $ qs] =
-          let val e' = lc_tr ctxt [e, q, qs];
-          in concatC $ (mapC $ (fst (abs_tr ctxt p e' false)) $ es) end;
-
-  in [(@{syntax_const "_listcompr"}, lc_tr)] end
+let
+  val NilC = Syntax.const @{const_syntax Nil};
+  val ConsC = Syntax.const @{const_syntax Cons};
+  val mapC = Syntax.const @{const_syntax map};
+  val concatC = Syntax.const @{const_syntax concat};
+  val IfC = Syntax.const @{const_syntax If};
+  val dummyC = Syntax.const @{const_syntax Pure.dummy_pattern}
+
+  fun single x = ConsC $ x $ NilC;
+
+  fun pat_tr ctxt p e opti = (* %x. case x of p => e | _ => [] *)
+    let
+      (* FIXME proper name context!? *)
+      val x =
+        Free (singleton (Name.variant_list (fold Term.add_free_names [p, e] [])) "x", dummyT);
+      val e = if opti then single e else e;
+      val case1 = Syntax.const @{syntax_const "_case1"} $ p $ e;
+      val case2 =
+        Syntax.const @{syntax_const "_case1"} $ dummyC $ NilC;
+      val cs = Syntax.const @{syntax_const "_case2"} $ case1 $ case2;
+    in Syntax_Trans.abs_tr [x, Case_Translation.case_tr false ctxt [x, cs]] end;
+
+  fun pair_pat_tr (x as Free _) e = Syntax_Trans.abs_tr [x, e]
+    | pair_pat_tr (_ $ p1 $ p2) e =
+        Syntax.const @{const_syntax case_prod} $ pair_pat_tr p1 (pair_pat_tr p2 e)
+    | pair_pat_tr dummy e = Syntax_Trans.abs_tr [Syntax.const "_idtdummy", e]
+
+  fun pair_pat ctxt (Const (@{const_syntax "Pair"},_) $ s $ t) =
+        pair_pat ctxt s andalso pair_pat ctxt t
+    | pair_pat ctxt (Free (s,_)) =
+        let
+          val thy = Proof_Context.theory_of ctxt;
+          val s' = Proof_Context.intern_const ctxt s;
+        in not (Sign.declared_const thy s') end
+    | pair_pat _ t = (t = dummyC);
+
+  fun abs_tr ctxt p e opti =
+    let val p = Term_Position.strip_positions p
+    in if pair_pat ctxt p
+       then (pair_pat_tr p e, true)
+       else (pat_tr ctxt p e opti, false)
+    end
+
+  fun lc_tr ctxt [e, Const (@{syntax_const "_lc_test"}, _) $ b, qs] =
+    let
+      val res =
+        (case qs of
+           Const (@{syntax_const "_lc_end"}, _) => single e
+         | Const (@{syntax_const "_lc_quals"}, _) $ q $ qs => lc_tr ctxt [e, q, qs]);
+    in IfC $ b $ res $ NilC end
+  | lc_tr ctxt
+      [e, Const (@{syntax_const "_lc_gen"}, _) $ p $ es,
+          Const(@{syntax_const "_lc_end"}, _)] =
+      (case abs_tr ctxt p e true of
+         (f, true) => mapC $ f $ es
+       | (f, false) => concatC $ (mapC $ f $ es))
+  | lc_tr ctxt
+      [e, Const (@{syntax_const "_lc_gen"}, _) $ p $ es,
+          Const (@{syntax_const "_lc_quals"}, _) $ q $ qs] =
+      let val e' = lc_tr ctxt [e, q, qs];
+      in concatC $ (mapC $ (fst (abs_tr ctxt p e' false)) $ es) end;
+
+in [(@{syntax_const "_listcompr"}, lc_tr)] end
 \<close>
 
 ML_val \<open>
@@ -513,8 +508,8 @@
           quote (Input.source_content s1) ^ Position.here_list [Input.pos_of s1, Input.pos_of s2]);
   in
     check \<open>[(x,y,z). b]\<close> \<open>if b then [(x, y, z)] else []\<close>;
-    check \<open>[(x,y,z). x\<leftarrow>xs]\<close> \<open>map (\<lambda>x. (x, y, z)) xs\<close>;
-    check \<open>[e x y. x\<leftarrow>xs, y\<leftarrow>ys]\<close> \<open>concat (map (\<lambda>x. map (\<lambda>y. e x y) ys) xs)\<close>;
+    check \<open>[(x,y,z). (x,_,y)\<leftarrow>xs]\<close> \<open>map (\<lambda>(x,_,y). (x, y, z)) xs\<close>;
+    check \<open>[e x y. (x,_)\<leftarrow>xs, y\<leftarrow>ys]\<close> \<open>concat (map (\<lambda>(x,_). map (\<lambda>y. e x y) ys) xs)\<close>;
     check \<open>[(x,y,z). x<a, x>b]\<close> \<open>if x < a then if b < x then [(x, y, z)] else [] else []\<close>;
     check \<open>[(x,y,z). x\<leftarrow>xs, x>b]\<close> \<open>concat (map (\<lambda>x. if b < x then [(x, y, z)] else []) xs)\<close>;
     check \<open>[(x,y,z). x<a, x\<leftarrow>xs]\<close> \<open>if x < a then map (\<lambda>x. (x, y, z)) xs else []\<close>;
@@ -526,26 +521,21 @@
       \<open>if x < a then if b < x then if x = d then [(x, y, z)] else [] else [] else []\<close>;
     check \<open>[(x,y,z). x<a, x>b, y\<leftarrow>ys]\<close>
       \<open>if x < a then if b < x then map (\<lambda>y. (x, y, z)) ys else [] else []\<close>;
-    check \<open>[(x,y,z). x<a, x\<leftarrow>xs,y>b]\<close>
-      \<open>if x < a then concat (map (\<lambda>x. if b < y then [(x, y, z)] else []) xs) else []\<close>;
+    check \<open>[(x,y,z). x<a, (_,x)\<leftarrow>xs,y>b]\<close>
+      \<open>if x < a then concat (map (\<lambda>(_,x). if b < y then [(x, y, z)] else []) xs) else []\<close>;
     check \<open>[(x,y,z). x<a, x\<leftarrow>xs, y\<leftarrow>ys]\<close>
       \<open>if x < a then concat (map (\<lambda>x. map (\<lambda>y. (x, y, z)) ys) xs) else []\<close>;
     check \<open>[(x,y,z). x\<leftarrow>xs, x>b, y<a]\<close>
       \<open>concat (map (\<lambda>x. if b < x then if y < a then [(x, y, z)] else [] else []) xs)\<close>;
     check \<open>[(x,y,z). x\<leftarrow>xs, x>b, y\<leftarrow>ys]\<close>
       \<open>concat (map (\<lambda>x. if b < x then map (\<lambda>y. (x, y, z)) ys else []) xs)\<close>;
-    check \<open>[(x,y,z). x\<leftarrow>xs, y\<leftarrow>ys,y>x]\<close>
-      \<open>concat (map (\<lambda>x. concat (map (\<lambda>y. if x < y then [(x, y, z)] else []) ys)) xs)\<close>;
+    check \<open>[(x,y,z). x\<leftarrow>xs, (y,_)\<leftarrow>ys,y>x]\<close>
+      \<open>concat (map (\<lambda>x. concat (map (\<lambda>(y,_). if x < y then [(x, y, z)] else []) ys)) xs)\<close>;
     check \<open>[(x,y,z). x\<leftarrow>xs, y\<leftarrow>ys,z\<leftarrow>zs]\<close>
       \<open>concat (map (\<lambda>x. concat (map (\<lambda>y. map (\<lambda>z. (x, y, z)) zs) ys)) xs)\<close>
   end;
 \<close>
 
-(*
-term "[(x,y). x\<leftarrow>xs, let xx = x+x, y\<leftarrow>ys, y \<noteq> xx]"
-*)
-
-
 ML \<open>
 (* Simproc for rewriting list comprehensions applied to List.set to set
    comprehension. *)