src/HOL/Tools/Predicate_Compile/code_prolog.ML
changeset 38735 cb9031a9dccf
parent 38734 e5508a74b11f
child 38755 a37d39fe32f8
child 38786 e46e7a9cb622
child 38789 d171840881fd
equal deleted inserted replaced
38734:e5508a74b11f 38735:cb9031a9dccf
    56 datatype arith_op = Plus | Minus
    56 datatype arith_op = Plus | Minus
    57 
    57 
    58 datatype prol_term = Var of string | Cons of string | AppF of string * prol_term list
    58 datatype prol_term = Var of string | Cons of string | AppF of string * prol_term list
    59   | Number of int | ArithOp of arith_op * prol_term list;
    59   | Number of int | ArithOp of arith_op * prol_term list;
    60 
    60 
       
    61 fun dest_Var (Var v) = v
       
    62 
       
    63 fun add_vars (Var v) = insert (op =) v
       
    64   | add_vars (ArithOp (_, ts)) = fold add_vars ts
       
    65   | add_vars (AppF (_, ts)) = fold add_vars ts
       
    66   | add_vars _ = I
       
    67 
       
    68 fun map_vars f (Var v) = Var (f v)
       
    69   | map_vars f (ArithOp (opr, ts)) = ArithOp (opr, map (map_vars f) ts)
       
    70   | map_vars f (AppF (fs, ts)) = AppF (fs, map (map_vars f) ts)
       
    71   | map_vars f t = t
       
    72   
    61 fun maybe_AppF (c, []) = Cons c
    73 fun maybe_AppF (c, []) = Cons c
    62   | maybe_AppF (c, xs) = AppF (c, xs)
    74   | maybe_AppF (c, xs) = AppF (c, xs)
    63 
    75 
    64 fun is_Var (Var _) = true
    76 fun is_Var (Var _) = true
    65   | is_Var _ = false
    77   | is_Var _ = false
    77 datatype prem = Conj of prem list
    89 datatype prem = Conj of prem list
    78   | Rel of string * prol_term list | NotRel of string * prol_term list
    90   | Rel of string * prol_term list | NotRel of string * prol_term list
    79   | Eq of prol_term * prol_term | NotEq of prol_term * prol_term
    91   | Eq of prol_term * prol_term | NotEq of prol_term * prol_term
    80   | ArithEq of prol_term * prol_term | NotArithEq of prol_term * prol_term
    92   | ArithEq of prol_term * prol_term | NotArithEq of prol_term * prol_term
    81   | Ground of string * typ;
    93   | Ground of string * typ;
    82   
    94 
    83 fun dest_Rel (Rel (c, ts)) = (c, ts)
    95 fun dest_Rel (Rel (c, ts)) = (c, ts)
    84  
    96 
       
    97 fun map_term_prem f (Conj prems) = Conj (map (map_term_prem f) prems)
       
    98   | map_term_prem f (Rel (r, ts)) = Rel (r, map f ts)
       
    99   | map_term_prem f (NotRel (r, ts)) = NotRel (r, map f ts)
       
   100   | map_term_prem f (Eq (l, r)) = Eq (f l, f r)
       
   101   | map_term_prem f (NotEq (l, r)) = NotEq (f l, f r)
       
   102   | map_term_prem f (ArithEq (l, r)) = ArithEq (f l, f r)
       
   103   | map_term_prem f (NotArithEq (l, r)) = NotArithEq (f l, f r)
       
   104   | map_term_prem f (Ground (v, T)) = Ground (dest_Var (f (Var v)), T)
       
   105 
       
   106 fun fold_prem_terms f (Conj prems) = fold (fold_prem_terms f) prems
       
   107   | fold_prem_terms f (Rel (_, ts)) = fold f ts
       
   108   | fold_prem_terms f (NotRel (_, ts)) = fold f ts
       
   109   | fold_prem_terms f (Eq (l, r)) = f l #> f r
       
   110   | fold_prem_terms f (NotEq (l, r)) = f l #> f r
       
   111   | fold_prem_terms f (ArithEq (l, r)) = f l #> f r
       
   112   | fold_prem_terms f (NotArithEq (l, r)) = f l #> f r
       
   113   | fold_prem_terms f (Ground (v, T)) = f (Var v)
       
   114   
    85 type clause = ((string * prol_term list) * prem);
   115 type clause = ((string * prol_term list) * prem);
    86 
   116 
    87 type logic_program = clause list;
   117 type logic_program = clause list;
    88 
   118 
    89 (* translation from introduction rules to internal representation *)
   119 (* translation from introduction rules to internal representation *)
   306     val p' = map (apsnd replace_ground) p
   336     val p' = map (apsnd replace_ground) p
   307   in
   337   in
   308     ((flat grs) @ p', constant_table')
   338     ((flat grs) @ p', constant_table')
   309   end
   339   end
   310     
   340     
       
   341 (* rename variables to prolog-friendly names *)
       
   342 
       
   343 fun rename_vars_term renaming = map_vars (fn v => the (AList.lookup (op =) renaming v))
       
   344 
       
   345 fun rename_vars_prem renaming = map_term_prem (rename_vars_term renaming)
       
   346 
       
   347 fun dest_Char (Symbol.Char c) = c
       
   348 
       
   349 fun is_prolog_conform v =
       
   350   forall (fn s => Symbol.is_ascii_letter s orelse Symbol.is_ascii_digit s) (Symbol.explode v)
       
   351 
       
   352 fun mk_conform avoid v =
       
   353   let 
       
   354     val v' = space_implode "" (map (dest_Char o Symbol.decode)
       
   355       (filter (fn s => Symbol.is_ascii_letter s orelse Symbol.is_ascii_digit s)
       
   356         (Symbol.explode v)))
       
   357     val v' = if v' = "" then "var" else v'
       
   358   in Name.variant avoid (first_upper v') end
       
   359   
       
   360 fun mk_renaming v renaming =
       
   361   (v, mk_conform (map snd renaming) v) :: renaming
       
   362 
       
   363 fun rename_vars_clause ((rel, args), prem) =
       
   364   let
       
   365     val vars = fold_prem_terms add_vars prem (fold add_vars args [])
       
   366     val renaming = fold mk_renaming vars []
       
   367   in ((rel, map (rename_vars_term renaming) args), rename_vars_prem renaming prem) end
       
   368   
       
   369 val rename_vars_program = map rename_vars_clause
       
   370   
   311 (* code printer *)
   371 (* code printer *)
   312 
   372 
   313 fun write_arith_op Plus = "+"
   373 fun write_arith_op Plus = "+"
   314   | write_arith_op Minus = "-"
   374   | write_arith_op Minus = "-"
   315 
   375 
   316 fun write_term (Var v) = first_upper v
   376 fun write_term (Var v) = v
   317   | write_term (Cons c) = c
   377   | write_term (Cons c) = c
   318   | write_term (AppF (f, args)) = f ^ "(" ^ space_implode ", " (map write_term args) ^ ")"
   378   | write_term (AppF (f, args)) = f ^ "(" ^ space_implode ", " (map write_term args) ^ ")"
   319   | write_term (ArithOp (oper, [a1, a2])) = write_term a1 ^ " " ^ write_arith_op oper ^ " " ^ write_term a2
   379   | write_term (ArithOp (oper, [a1, a2])) = write_term a1 ^ " " ^ write_arith_op oper ^ " " ^ write_term a2
   320   | write_term (Number n) = string_of_int n
   380   | write_term (Number n) = string_of_int n
   321 
   381 
   412 (* calling external interpreter and getting results *)
   472 (* calling external interpreter and getting results *)
   413 
   473 
   414 fun run p query_rel vnames nsols =
   474 fun run p query_rel vnames nsols =
   415   let
   475   let
   416     val cmd = Path.named_root
   476     val cmd = Path.named_root
   417     val query = case nsols of NONE => query_first | SOME n => query_firstn n 
   477     val query = case nsols of NONE => query_first | SOME n => query_firstn n
   418     val prog = prelude ^ query query_rel vnames ^ write_program p
   478     val p' = rename_vars_program p
       
   479     val _ = tracing "Renaming variable names..."
       
   480     val renaming = fold mk_renaming vnames [] 
       
   481     val vnames' = map (fn v => the (AList.lookup (op =) renaming v)) vnames
       
   482     val prog = prelude ^ query query_rel vnames' ^ write_program p'
   419     val _ = tracing ("Generated prolog program:\n" ^ prog)
   483     val _ = tracing ("Generated prolog program:\n" ^ prog)
   420     val prolog_file = File.tmp_path (Path.basic "prolog_file")
   484     val prolog_file = File.tmp_path (Path.basic "prolog_file")
   421     val _ = File.write prolog_file prog
   485     val _ = File.write prolog_file prog
   422     val (solution, _) = bash_output ("/usr/local/bin/swipl -f " ^ File.shell_path prolog_file)
   486     val (solution, _) = bash_output ("/usr/local/bin/swipl -f " ^ File.shell_path prolog_file)
   423     val _ = tracing ("Prolog returned solution(s):\n" ^ solution)
   487     val _ = tracing ("Prolog returned solution(s):\n" ^ solution)
   563     val ctxt'' = ProofContext.init_global thy3
   627     val ctxt'' = ProofContext.init_global thy3
   564     val _ = tracing "Generating prolog program..."
   628     val _ = tracing "Generating prolog program..."
   565     val (p, constant_table) = generate {ensure_groundness = true} ctxt'' full_constname
   629     val (p, constant_table) = generate {ensure_groundness = true} ctxt'' full_constname
   566       |> add_ground_predicates ctxt''
   630       |> add_ground_predicates ctxt''
   567     val _ = tracing "Running prolog program..."
   631     val _ = tracing "Running prolog program..."
   568     val [ts] = run p (translate_const constant_table full_constname) (map (first_upper o fst) vs')
   632     val [ts] = run p (translate_const constant_table full_constname) (map fst vs')
   569       (SOME 1)
   633       (SOME 1)
   570     val _ = tracing "Restoring terms..."
   634     val _ = tracing "Restoring terms..."
   571     val res = SOME (map (restore_term ctxt'' constant_table) (ts ~~ Ts))
   635     val res = SOME (map (restore_term ctxt'' constant_table) (ts ~~ Ts))
   572     val empty_report = ([], false)
   636     val empty_report = ([], false)
   573   in
   637   in