src/HOL/Tools/Nunchaku/nunchaku_model.ML
changeset 66614 1f1c5d85d232
parent 64389 6273d4c8325b
child 66616 ee56847876b2
equal deleted inserted replaced
66613:db3969568560 66614:1f1c5d85d232
       
     1 (*  Title:      HOL/Nunchaku/Tools/nunchaku_model.ML
       
     2     Author:     Jasmin Blanchette, VU Amsterdam
       
     3     Copyright   2015, 2016, 2017
       
     4 
       
     5 Abstract syntax tree for Nunchaku models.
       
     6 *)
       
     7 
       
     8 signature NUNCHAKU_MODEL =
       
     9 sig
       
    10   type ident = Nunchaku_Problem.ident
       
    11   type ty = Nunchaku_Problem.ty
       
    12   type tm = Nunchaku_Problem.tm
       
    13   type name_pool = Nunchaku_Problem.name_pool
       
    14 
       
    15   type ty_entry = ty * tm list
       
    16   type tm_entry = tm * tm
       
    17 
       
    18   type nun_model =
       
    19     {type_model: ty_entry list,
       
    20      const_model: tm_entry list,
       
    21      skolem_model: tm_entry list}
       
    22 
       
    23   val str_of_nun_model: nun_model -> string
       
    24 
       
    25   val allocate_ugly: name_pool -> string * string -> string * name_pool
       
    26 
       
    27   val ugly_nun_model: name_pool -> nun_model -> nun_model
       
    28 
       
    29   datatype token =
       
    30     Ident of ident
       
    31   | Symbol of ident
       
    32   | Atom of ident * int
       
    33   | End_of_Stream
       
    34 
       
    35   val parse_tok: ''a -> ''a list -> ''a * ''a list
       
    36   val parse_ident: token list -> ident * token list
       
    37   val parse_id: ident -> token list -> token * token list
       
    38   val parse_sym: ident -> token list -> token * token list
       
    39   val parse_atom: token list -> (ident * int) * token list
       
    40   val nun_model_of_str: string -> nun_model
       
    41 end;
       
    42 
       
    43 structure Nunchaku_Model : NUNCHAKU_MODEL =
       
    44 struct
       
    45 
       
    46 open Nunchaku_Problem;
       
    47 
       
    48 type ty_entry = ty * tm list;
       
    49 type tm_entry = tm * tm;
       
    50 
       
    51 type nun_model =
       
    52   {type_model: ty_entry list,
       
    53    const_model: tm_entry list,
       
    54    skolem_model: tm_entry list};
       
    55 
       
    56 val nun_SAT = str_of_ident "SAT";
       
    57 
       
    58 fun str_of_ty_entry (ty, tms) =
       
    59   "type " ^ str_of_ty ty ^ " := {" ^ commas (map str_of_tm tms) ^ "}.";
       
    60 
       
    61 fun str_of_tm_entry (tm, value) =
       
    62   "val " ^ str_of_tm tm ^ " := " ^ str_of_tm value ^ ".";
       
    63 
       
    64 fun str_of_nun_model {type_model, const_model, skolem_model} =
       
    65   map str_of_ty_entry type_model @ "" :: map str_of_tm_entry const_model @ "" ::
       
    66   map str_of_tm_entry skolem_model
       
    67   |> cat_lines;
       
    68 
       
    69 fun fold_map_ty_entry_idents f (ty, atoms) =
       
    70   fold_map_ty_idents f ty
       
    71   ##>> fold_map (fold_map_tm_idents f) atoms;
       
    72 
       
    73 fun fold_map_tm_entry_idents f (tm, value) =
       
    74   fold_map_tm_idents f tm
       
    75   ##>> fold_map_tm_idents f value;
       
    76 
       
    77 fun fold_map_nun_model_idents f {type_model, const_model, skolem_model} =
       
    78   fold_map (fold_map_ty_entry_idents f) type_model
       
    79   ##>> fold_map (fold_map_tm_entry_idents f) const_model
       
    80   ##>> fold_map (fold_map_tm_entry_idents f) skolem_model
       
    81   #>> (fn ((type_model, const_model), skolem_model) =>
       
    82     {type_model = type_model, const_model = const_model, skolem_model = skolem_model});
       
    83 
       
    84 fun swap_name_pool ({nice_of_ugly, ugly_of_nice} : name_pool) =
       
    85   {nice_of_ugly = ugly_of_nice, ugly_of_nice = nice_of_ugly};
       
    86 
       
    87 fun allocate_ugly pool (nice, ugly_sugg) =
       
    88   allocate_nice (swap_name_pool pool) (nice, ugly_sugg) ||> swap_name_pool;
       
    89 
       
    90 fun ugly_ident nice (pool as {ugly_of_nice, ...}) =
       
    91   (case Symtab.lookup ugly_of_nice nice of
       
    92     NONE => allocate_ugly pool (nice, nice)
       
    93   | SOME ugly => (ugly, pool));
       
    94 
       
    95 fun ugly_nun_model pool model =
       
    96   fst (fold_map_nun_model_idents ugly_ident model pool);
       
    97 
       
    98 datatype token =
       
    99   Ident of ident
       
   100 | Symbol of ident
       
   101 | Atom of ident * int
       
   102 | End_of_Stream;
       
   103 
       
   104 val rev_str = String.implode o rev o String.explode;
       
   105 
       
   106 fun atom_of_str s =
       
   107   (case first_field "_" (rev_str s) of
       
   108     SOME (rev_suf, rev_pre) =>
       
   109     let
       
   110       val pre = rev_str rev_pre;
       
   111       val suf = rev_str rev_suf;
       
   112     in
       
   113       (case Int.fromString suf of
       
   114         SOME j => Atom (ident_of_str pre, j)
       
   115       | NONE => raise Fail "ill-formed atom")
       
   116     end
       
   117   | NONE => raise Fail "ill-formed atom");
       
   118 
       
   119 fun is_alnum_etc_char c = Char.isAlphaNum c orelse c = #"_" orelse c = #"/";
       
   120 
       
   121 val multi_ids =
       
   122   [nun_arrow, nun_assign, nun_conj, nun_disj, nun_implies, nun_unparsable, nun_irrelevant];
       
   123 
       
   124 val nun_anon_fun_prefix_exploded = String.explode nun_anon_fun_prefix;
       
   125 val [nun_dollar_char] = String.explode nun_dollar;
       
   126 
       
   127 fun next_token [] = (End_of_Stream, [])
       
   128   | next_token (c :: cs) =
       
   129     if Char.isSpace c then
       
   130       next_token cs
       
   131     else if c = nun_dollar_char then
       
   132       let val n = find_index (not o is_alnum_etc_char) cs in
       
   133         (if n = ~1 then (cs, []) else chop n cs)
       
   134         |>> (String.implode
       
   135           #> (if is_prefix (op =) nun_anon_fun_prefix_exploded cs then ident_of_str #> Ident
       
   136             else atom_of_str))
       
   137       end
       
   138     else if is_alnum_etc_char c then
       
   139       let val n = find_index (not o is_alnum_etc_char) cs in
       
   140         (if n = ~1 then (cs, []) else chop n cs)
       
   141         |>> (cons c #> String.implode #> ident_of_str #> Ident)
       
   142       end
       
   143     else
       
   144       let
       
   145         fun next_multi id =
       
   146           let
       
   147             val s = str_of_ident id;
       
   148             val n = String.size s - 1;
       
   149           in
       
   150             if c = String.sub (s, 0) andalso
       
   151                is_prefix (op =) (String.explode (String.substring (s, 1, n))) cs then
       
   152               SOME (Symbol id, drop n cs)
       
   153             else
       
   154               NONE
       
   155           end;
       
   156       in
       
   157         (case get_first next_multi multi_ids of
       
   158           SOME res => res
       
   159         | NONE => (Symbol (ident_of_str (String.str c)), cs))
       
   160       end;
       
   161 
       
   162 val tokenize =
       
   163   let
       
   164     fun toks cs =
       
   165       (case next_token cs of
       
   166         (End_of_Stream, []) => []
       
   167       | (tok, cs') => tok :: toks cs');
       
   168   in
       
   169     toks o String.explode
       
   170   end;
       
   171 
       
   172 fun parse_enum sep scan = scan ::: Scan.repeat (sep |-- scan);
       
   173 
       
   174 fun parse_tok tok = Scan.one (curry (op =) tok);
       
   175 
       
   176 val parse_ident = Scan.some (try (fn Ident id => id));
       
   177 val parse_id = parse_tok o Ident;
       
   178 val parse_sym = parse_tok o Symbol;
       
   179 val parse_atom = Scan.some (try (fn Atom id_j => id_j));
       
   180 
       
   181 val confusing_ids = [nun_else, nun_then, nun_with];
       
   182 
       
   183 val parse_confusing_id = Scan.one (fn Ident id => member (op =) confusing_ids id | _ => false);
       
   184 
       
   185 fun parse_ty toks =
       
   186   (parse_ty_arg -- Scan.option (parse_sym nun_arrow -- parse_ty)
       
   187    >> (fn (ty, NONE) => ty
       
   188      | (lhs, SOME (Symbol id, rhs)) => NType (id, [lhs, rhs]))) toks
       
   189 and parse_ty_arg toks =
       
   190   (parse_ident >> (rpair [] #> NType)
       
   191    || parse_sym nun_lparen |-- parse_ty --| parse_sym nun_rparen) toks;
       
   192 
       
   193 val parse_choice_or_unique =
       
   194   (parse_tok (Ident nun_choice) || parse_tok (Ident nun_unique)
       
   195    || parse_tok (Ident nun_unique_unsafe))
       
   196   -- parse_ty_arg
       
   197   >> (fn (Ident id, ty) => NConst (id, [ty], mk_arrows_ty ([ty, prop_ty], ty)));
       
   198 
       
   199 fun parse_tm toks =
       
   200   (parse_id nun_lambda |-- Scan.repeat parse_arg --| parse_sym nun_dot -- parse_tm >> nabss
       
   201   || parse_id nun_mu |-- parse_arg --| parse_sym nun_dot -- parse_tm
       
   202      >> (fn (var, body) =>
       
   203        let val ty = safe_ty_of body in
       
   204          NApp (NConst (nun_mu, [ty], mk_arrow_ty (mk_arrow_ty (ty, ty), ty)), NAbs (var, body))
       
   205        end)
       
   206    || parse_id nun_if |-- parse_tm --| parse_id nun_then -- parse_tm --| parse_id nun_else
       
   207        -- parse_tm
       
   208      >> (fn ((cond, th), el) =>
       
   209        let val ty = safe_ty_of th in
       
   210          napps (NConst (nun_if, [ty], mk_arrows_ty ([prop_ty, ty, ty], ty)), [cond, th, el])
       
   211        end)
       
   212    || parse_implies) toks
       
   213 and parse_implies toks =
       
   214   (parse_disj -- Scan.option (parse_sym nun_implies -- parse_implies)
       
   215    >> (fn (tm, NONE) => tm
       
   216      | (lhs, SOME (Symbol id, rhs)) => napps (NConst (id, [], dummy_ty), [lhs, rhs]))) toks
       
   217 and parse_disj toks =
       
   218   (parse_conj -- Scan.option (parse_sym nun_disj -- parse_disj)
       
   219    >> (fn (tm, NONE) => tm
       
   220      | (lhs, SOME (Symbol id, rhs)) => napps (NConst (id, [], dummy_ty), [lhs, rhs]))) toks
       
   221 and parse_conj toks =
       
   222   (parse_equals -- Scan.option (parse_sym nun_conj -- parse_conj)
       
   223    >> (fn (tm, NONE) => tm
       
   224      | (lhs, SOME (Symbol id, rhs)) => napps (NConst (id, [], dummy_ty), [lhs, rhs]))) toks
       
   225 and parse_equals toks =
       
   226   (parse_comb -- Scan.option (parse_sym nun_equals -- parse_comb)
       
   227    >> (fn (tm, NONE) => tm
       
   228      | (lhs, SOME (Symbol id, rhs)) => napps (NConst (id, [], dummy_ty), [lhs, rhs]))) toks
       
   229 and parse_comb toks =
       
   230   (parse_arg -- Scan.repeat (Scan.unless parse_confusing_id parse_arg) >> napps) toks
       
   231 and parse_arg toks =
       
   232   (parse_choice_or_unique
       
   233    || parse_ident >> (fn id => NConst (id, [], dummy_ty))
       
   234    || parse_sym nun_irrelevant
       
   235       |-- Scan.option (parse_sym nun_lparen |-- parse_tm --| parse_sym nun_rparen) (* FIXME *)
       
   236      >> (fn _ => NConst (nun_irrelevant, [], dummy_ty))
       
   237    || parse_sym nun_unparsable |-- parse_ty >> (fn ty => NConst (nun_unparsable, [], ty))
       
   238    || parse_sym nun_lparen |-- parse_tm -- Scan.option (parse_sym nun_colon |-- parse_ty)
       
   239       --| parse_sym nun_rparen
       
   240      >> (fn (NConst (id, [], _), SOME ty) => NConst (id, [], ty)
       
   241        | (tm, _) => tm)
       
   242    || parse_atom >> (fn (id, j) => NAtom (j, NType (id, [])))) toks;
       
   243 
       
   244 val parse_witness_name =
       
   245   parse_ident >> (fn id => NConst (hd (space_explode "/" id), [], dummy_ty));
       
   246 
       
   247 val parse_witness =
       
   248   parse_id nun__witness_of |-- parse_sym nun_lparen |-- (parse_id nun_forall || parse_id nun_exists)
       
   249   |-- Scan.option (parse_sym nun_lparen) |-- parse_witness_name
       
   250   --| Scan.repeat (Scan.one (curry (op <>) (Symbol nun_assign)));
       
   251 
       
   252 datatype entry =
       
   253   Type_Entry of ty_entry
       
   254 | Skolem_Entry of tm_entry
       
   255 | Const_Entry of tm_entry;
       
   256 
       
   257 val parse_entry =
       
   258   (parse_id nun_type |-- parse_ty --| parse_sym nun_assign --| parse_sym nun_lbrace --
       
   259        parse_enum (parse_sym nun_comma) parse_tm --| parse_sym nun_rbrace
       
   260      >> Type_Entry
       
   261    || parse_id nun_val |-- parse_witness --| parse_sym nun_assign -- parse_tm >> Skolem_Entry
       
   262    || parse_id nun_val |-- parse_tm --| parse_sym nun_assign -- parse_tm >> Const_Entry)
       
   263   --| parse_sym nun_dot;
       
   264 
       
   265 val parse_model =
       
   266   parse_id nun_SAT |-- parse_sym nun_colon |-- parse_sym nun_lbrace |-- Scan.repeat parse_entry
       
   267   --| parse_sym nun_rbrace;
       
   268 
       
   269 fun add_entry entry ({type_model, const_model, skolem_model} : nun_model) =
       
   270   (case entry of
       
   271     Type_Entry e =>
       
   272     {type_model = e :: type_model, const_model = const_model, skolem_model = skolem_model}
       
   273   | Skolem_Entry e =>
       
   274     {type_model = type_model, const_model = const_model, skolem_model = e :: skolem_model}
       
   275   | Const_Entry e =>
       
   276     {type_model = type_model, const_model = e :: const_model, skolem_model = skolem_model});
       
   277 
       
   278 fun nun_model_of_str str =
       
   279   let val (entries, _) = parse_model (tokenize str) in
       
   280     {type_model = [], const_model = [], skolem_model = []}
       
   281     |> fold_rev add_entry entries
       
   282   end;
       
   283 
       
   284 end;