wenzelm@42243: (* Title: Pure/Syntax/syntax_phases.ML wenzelm@42241: Author: Makarius wenzelm@42241: wenzelm@42243: Main phases of inner syntax processing, with standard implementations wenzelm@42243: of parse/unparse operations. wenzelm@42241: *) wenzelm@42241: wenzelm@42243: signature SYNTAX_PHASES = wenzelm@42242: sig wenzelm@42242: val term_sorts: term -> (indexname * sort) list wenzelm@42242: val typ_of_term: (indexname -> sort) -> term -> typ wenzelm@42242: val decode_term: Proof.context -> wenzelm@42242: Position.reports * term Exn.result -> Position.reports * term Exn.result wenzelm@42242: val parse_ast_pattern: Proof.context -> string * string -> Ast.ast wenzelm@42247: val term_of_typ: Proof.context -> typ -> term wenzelm@42242: end wenzelm@42242: wenzelm@42243: structure Syntax_Phases: SYNTAX_PHASES = wenzelm@42241: struct wenzelm@42241: wenzelm@42298: (** markup logical entities **) wenzelm@42298: wenzelm@42298: fun markup_class ctxt c = wenzelm@42298: [Name_Space.markup_entry (Type.class_space (ProofContext.tsig_of ctxt)) c]; wenzelm@42298: wenzelm@42298: fun markup_type ctxt c = wenzelm@42298: [Name_Space.markup_entry (Type.type_space (ProofContext.tsig_of ctxt)) c]; wenzelm@42298: wenzelm@42298: fun markup_const ctxt c = wenzelm@42298: [Name_Space.markup_entry (Consts.space_of (ProofContext.consts_of ctxt)) c]; wenzelm@42298: wenzelm@42298: fun markup_free ctxt x = wenzelm@42298: [if can Name.dest_skolem x then Markup.skolem else Markup.free] @ wenzelm@42298: (if not (Variable.is_body ctxt) orelse Variable.is_fixed ctxt x then [] wenzelm@42298: else [Markup.hilite]); wenzelm@42298: wenzelm@42298: fun markup_var xi = [Markup.name (Term.string_of_vname xi) Markup.var]; wenzelm@42298: wenzelm@42298: fun markup_bound def id = wenzelm@42298: [Markup.properties [(if def then Markup.defN else Markup.refN, id)] Markup.bound]; wenzelm@42298: wenzelm@42298: fun markup_entity ctxt c = wenzelm@42298: (case Syntax.lookup_const (ProofContext.syn_of ctxt) c of wenzelm@42298: SOME "" => [] wenzelm@42298: | SOME b => markup_entity ctxt b wenzelm@42298: | NONE => c |> Lexicon.unmark wenzelm@42298: {case_class = markup_class ctxt, wenzelm@42298: case_type = markup_type ctxt, wenzelm@42298: case_const = markup_const ctxt, wenzelm@42298: case_fixed = markup_free ctxt, wenzelm@42298: case_default = K []}); wenzelm@42298: wenzelm@42298: wenzelm@42298: wenzelm@42242: (** decode parse trees **) wenzelm@42242: wenzelm@42242: (* sort_of_term *) wenzelm@42242: wenzelm@42242: fun sort_of_term tm = wenzelm@42242: let wenzelm@42242: fun err () = raise TERM ("sort_of_term: bad encoding of classes", [tm]); wenzelm@42242: wenzelm@42242: fun class s = Lexicon.unmark_class s handle Fail _ => err (); wenzelm@42242: wenzelm@42242: fun classes (Const (s, _)) = [class s] wenzelm@42242: | classes (Const ("_classes", _) $ Const (s, _) $ cs) = class s :: classes cs wenzelm@42242: | classes _ = err (); wenzelm@42242: wenzelm@42242: fun sort (Const ("_topsort", _)) = [] wenzelm@42242: | sort (Const (s, _)) = [class s] wenzelm@42242: | sort (Const ("_sort", _) $ cs) = classes cs wenzelm@42242: | sort _ = err (); wenzelm@42242: in sort tm end; wenzelm@42242: wenzelm@42242: wenzelm@42242: (* term_sorts *) wenzelm@42242: wenzelm@42242: fun term_sorts tm = wenzelm@42242: let wenzelm@42242: val sort_of = sort_of_term; wenzelm@42242: wenzelm@42242: fun add_env (Const ("_ofsort", _) $ Free (x, _) $ cs) = wenzelm@42242: insert (op =) ((x, ~1), sort_of cs) wenzelm@42242: | add_env (Const ("_ofsort", _) $ (Const ("_tfree", _) $ Free (x, _)) $ cs) = wenzelm@42242: insert (op =) ((x, ~1), sort_of cs) wenzelm@42242: | add_env (Const ("_ofsort", _) $ Var (xi, _) $ cs) = wenzelm@42242: insert (op =) (xi, sort_of cs) wenzelm@42242: | add_env (Const ("_ofsort", _) $ (Const ("_tvar", _) $ Var (xi, _)) $ cs) = wenzelm@42242: insert (op =) (xi, sort_of cs) wenzelm@42242: | add_env (Abs (_, _, t)) = add_env t wenzelm@42242: | add_env (t1 $ t2) = add_env t1 #> add_env t2 wenzelm@42242: | add_env _ = I; wenzelm@42242: in add_env tm [] end; wenzelm@42242: wenzelm@42242: wenzelm@42242: (* typ_of_term *) wenzelm@42242: wenzelm@42242: fun typ_of_term get_sort tm = wenzelm@42242: let wenzelm@42242: fun err () = raise TERM ("typ_of_term: bad encoding of type", [tm]); wenzelm@42242: wenzelm@42242: fun typ_of (Free (x, _)) = TFree (x, get_sort (x, ~1)) wenzelm@42242: | typ_of (Var (xi, _)) = TVar (xi, get_sort xi) wenzelm@42242: | typ_of (Const ("_tfree",_) $ (t as Free _)) = typ_of t wenzelm@42242: | typ_of (Const ("_tvar",_) $ (t as Var _)) = typ_of t wenzelm@42242: | typ_of (Const ("_ofsort", _) $ Free (x, _) $ _) = TFree (x, get_sort (x, ~1)) wenzelm@42242: | typ_of (Const ("_ofsort", _) $ (Const ("_tfree",_) $ Free (x, _)) $ _) = wenzelm@42242: TFree (x, get_sort (x, ~1)) wenzelm@42242: | typ_of (Const ("_ofsort", _) $ Var (xi, _) $ _) = TVar (xi, get_sort xi) wenzelm@42242: | typ_of (Const ("_ofsort", _) $ (Const ("_tvar",_) $ Var (xi, _)) $ _) = wenzelm@42242: TVar (xi, get_sort xi) wenzelm@42242: | typ_of (Const ("_dummy_ofsort", _) $ t) = TFree ("'_dummy_", sort_of_term t) wenzelm@42242: | typ_of t = wenzelm@42242: let wenzelm@42242: val (head, args) = Term.strip_comb t; wenzelm@42242: val a = wenzelm@42242: (case head of wenzelm@42242: Const (c, _) => (Lexicon.unmark_type c handle Fail _ => err ()) wenzelm@42242: | _ => err ()); wenzelm@42242: in Type (a, map typ_of args) end; wenzelm@42242: in typ_of tm end; wenzelm@42242: wenzelm@42242: wenzelm@42242: (* parsetree_to_ast *) wenzelm@42242: wenzelm@42242: fun parsetree_to_ast ctxt constrain_pos trf parsetree = wenzelm@42242: let wenzelm@42250: val get_class = ProofContext.read_class ctxt; wenzelm@42250: val get_type = #1 o dest_Type o ProofContext.read_type_name_proper ctxt false; wenzelm@42282: wenzelm@42242: val reports = Unsynchronized.ref ([]: Position.reports); wenzelm@42242: fun report pos = Position.reports reports [pos]; wenzelm@42242: wenzelm@42242: fun trans a args = wenzelm@42242: (case trf a of wenzelm@42242: NONE => Ast.mk_appl (Ast.Constant a) args wenzelm@42242: | SOME f => f ctxt args); wenzelm@42242: wenzelm@42282: fun asts_of (Parser.Node ("_class_name", [Parser.Tip tok])) = wenzelm@42242: let wenzelm@42242: val c = get_class (Lexicon.str_of_token tok); wenzelm@42298: val _ = report (Lexicon.pos_of_token tok) (markup_class ctxt) c; wenzelm@42282: in [Ast.Constant (Lexicon.mark_class c)] end wenzelm@42282: | asts_of (Parser.Node ("_type_name", [Parser.Tip tok])) = wenzelm@42242: let wenzelm@42242: val c = get_type (Lexicon.str_of_token tok); wenzelm@42298: val _ = report (Lexicon.pos_of_token tok) (markup_type ctxt) c; wenzelm@42282: in [Ast.Constant (Lexicon.mark_type c)] end wenzelm@42282: | asts_of (Parser.Node ("_constrain_position", [pt as Parser.Tip tok])) = wenzelm@42242: if constrain_pos then wenzelm@42282: [Ast.Appl [Ast.Constant "_constrain", ast_of pt, wenzelm@42282: Ast.Variable (Term_Position.encode (Lexicon.pos_of_token tok))]] wenzelm@42282: else [ast_of pt] wenzelm@42282: | asts_of (Parser.Node (a, pts)) = wenzelm@42282: let wenzelm@42282: val _ = pts |> List.app wenzelm@42282: (fn Parser.Node _ => () | Parser.Tip tok => wenzelm@42282: if Lexicon.valued_token tok then () wenzelm@42298: else report (Lexicon.pos_of_token tok) (markup_entity ctxt) a); wenzelm@42282: in [trans a (maps asts_of pts)] end wenzelm@42282: | asts_of (Parser.Tip tok) = wenzelm@42282: if Lexicon.valued_token tok wenzelm@42282: then [Ast.Variable (Lexicon.str_of_token tok)] wenzelm@42282: else [] wenzelm@42282: wenzelm@42282: and ast_of pt = wenzelm@42282: (case asts_of pt of wenzelm@42282: [ast] => ast wenzelm@42282: | asts => raise Ast.AST ("parsetree_to_ast: malformed parsetree", asts)); wenzelm@42242: wenzelm@42242: val ast = Exn.interruptible_capture ast_of parsetree; wenzelm@42242: in (! reports, ast) end; wenzelm@42242: wenzelm@42242: wenzelm@42242: (* ast_to_term *) wenzelm@42242: wenzelm@42242: fun ast_to_term ctxt trf = wenzelm@42242: let wenzelm@42242: fun trans a args = wenzelm@42242: (case trf a of wenzelm@42242: NONE => Term.list_comb (Lexicon.const a, args) wenzelm@42242: | SOME f => f ctxt args); wenzelm@42242: wenzelm@42242: fun term_of (Ast.Constant a) = trans a [] wenzelm@42242: | term_of (Ast.Variable x) = Lexicon.read_var x wenzelm@42242: | term_of (Ast.Appl (Ast.Constant a :: (asts as _ :: _))) = wenzelm@42242: trans a (map term_of asts) wenzelm@42242: | term_of (Ast.Appl (ast :: (asts as _ :: _))) = wenzelm@42242: Term.list_comb (term_of ast, map term_of asts) wenzelm@42242: | term_of (ast as Ast.Appl _) = raise Ast.AST ("ast_to_term: malformed ast", [ast]); wenzelm@42242: in term_of end; wenzelm@42242: wenzelm@42242: wenzelm@42242: (* decode_term -- transform parse tree into raw term *) wenzelm@42242: wenzelm@42242: fun decode_term _ (result as (_: Position.reports, Exn.Exn _)) = result wenzelm@42242: | decode_term ctxt (reports0, Exn.Result tm) = wenzelm@42242: let wenzelm@42250: fun get_const a = wenzelm@42250: ((true, #1 (Term.dest_Const (ProofContext.read_const_proper ctxt false a))) wenzelm@42282: handle ERROR _ => (false, Consts.intern (ProofContext.consts_of ctxt) a)); wenzelm@42250: val get_free = ProofContext.intern_skolem ctxt; wenzelm@42250: wenzelm@42242: val decodeT = typ_of_term (ProofContext.get_sort ctxt (term_sorts tm)); wenzelm@42242: wenzelm@42242: val reports = Unsynchronized.ref reports0; wenzelm@42242: fun report ps = Position.reports reports ps; wenzelm@42242: wenzelm@42242: fun decode ps qs bs (Const ("_constrain", _) $ t $ typ) = wenzelm@42264: (case Term_Position.decode_position typ of wenzelm@42242: SOME p => decode (p :: ps) qs bs t wenzelm@42242: | NONE => Type.constraint (decodeT typ) (decode ps qs bs t)) wenzelm@42242: | decode ps qs bs (Const ("_constrainAbs", _) $ t $ typ) = wenzelm@42264: (case Term_Position.decode_position typ of wenzelm@42242: SOME q => decode ps (q :: qs) bs t wenzelm@42242: | NONE => Type.constraint (decodeT typ --> dummyT) (decode ps qs bs t)) wenzelm@42242: | decode _ qs bs (Abs (x, T, t)) = wenzelm@42242: let wenzelm@42242: val id = serial_string (); wenzelm@42242: val _ = report qs (markup_bound true) id; wenzelm@42242: in Abs (x, T, decode [] [] (id :: bs) t) end wenzelm@42242: | decode _ _ bs (t $ u) = decode [] [] bs t $ decode [] [] bs u wenzelm@42242: | decode ps _ _ (Const (a, T)) = wenzelm@42242: (case try Lexicon.unmark_fixed a of wenzelm@42282: SOME x => (report ps (markup_free ctxt) x; Free (x, T)) wenzelm@42242: | NONE => wenzelm@42242: let wenzelm@42242: val c = wenzelm@42242: (case try Lexicon.unmark_const a of wenzelm@42242: SOME c => c wenzelm@42242: | NONE => snd (get_const a)); wenzelm@42282: val _ = report ps (markup_const ctxt) c; wenzelm@42242: in Const (c, T) end) wenzelm@42242: | decode ps _ _ (Free (a, T)) = wenzelm@42242: (case (get_free a, get_const a) of wenzelm@42282: (SOME x, _) => (report ps (markup_free ctxt) x; Free (x, T)) wenzelm@42282: | (_, (true, c)) => (report ps (markup_const ctxt) c; Const (c, T)) wenzelm@42242: | (_, (false, c)) => wenzelm@42242: if Long_Name.is_qualified c wenzelm@42282: then (report ps (markup_const ctxt) c; Const (c, T)) wenzelm@42282: else (report ps (markup_free ctxt) c; Free (c, T))) wenzelm@42242: | decode ps _ _ (Var (xi, T)) = (report ps markup_var xi; Var (xi, T)) wenzelm@42242: | decode ps _ bs (t as Bound i) = wenzelm@42242: (case try (nth bs) i of wenzelm@42242: SOME id => (report ps (markup_bound false) id; t) wenzelm@42242: | NONE => t); wenzelm@42242: wenzelm@42242: val tm' = Exn.interruptible_capture (fn () => decode [] [] [] tm) (); wenzelm@42242: in (! reports, tm') end; wenzelm@42242: wenzelm@42242: wenzelm@42242: wenzelm@42242: (** parse **) wenzelm@42242: wenzelm@42242: (* results *) wenzelm@42242: wenzelm@42242: fun ambiguity_msg pos = "Parse error: ambiguous syntax" ^ Position.str_of pos; wenzelm@42242: wenzelm@42242: fun proper_results results = map_filter (fn (y, Exn.Result x) => SOME (y, x) | _ => NONE) results; wenzelm@42242: fun failed_results results = map_filter (fn (y, Exn.Exn e) => SOME (y, e) | _ => NONE) results; wenzelm@42242: wenzelm@42242: fun report ctxt = List.app (fn (pos, m) => Context_Position.report ctxt pos m); wenzelm@42242: wenzelm@42242: fun report_result ctxt pos results = wenzelm@42242: (case (proper_results results, failed_results results) of wenzelm@42242: ([], (reports, exn) :: _) => (report ctxt reports; reraise exn) wenzelm@42242: | ([(reports, x)], _) => (report ctxt reports; x) wenzelm@42242: | _ => error (ambiguity_msg pos)); wenzelm@42242: wenzelm@42242: wenzelm@42249: (* parse raw asts *) wenzelm@42242: wenzelm@42242: fun parse_asts ctxt raw root (syms, pos) = wenzelm@42242: let wenzelm@42251: val syn = ProofContext.syn_of ctxt; wenzelm@42253: val ast_tr = Syntax.parse_ast_translation syn; wenzelm@42242: wenzelm@42251: val toks = Syntax.tokenize syn raw syms; wenzelm@42242: val _ = List.app (Lexicon.report_token ctxt) toks; wenzelm@42242: wenzelm@42251: val pts = Syntax.parse ctxt syn root (filter Lexicon.is_proper toks) wenzelm@42242: handle ERROR msg => wenzelm@42242: error (msg ^ wenzelm@42242: implode (map (Markup.markup Markup.report o Lexicon.reported_token_range ctxt) toks)); wenzelm@42242: val len = length pts; wenzelm@42242: wenzelm@42242: val limit = Config.get ctxt Syntax.ambiguity_limit; wenzelm@42242: val _ = wenzelm@42242: if len <= Config.get ctxt Syntax.ambiguity_level then () wenzelm@42242: else if not (Config.get ctxt Syntax.ambiguity_enabled) then error (ambiguity_msg pos) wenzelm@42242: else wenzelm@42242: (Context_Position.if_visible ctxt warning (cat_lines wenzelm@42242: (("Ambiguous input" ^ Position.str_of pos ^ wenzelm@42242: "\nproduces " ^ string_of_int len ^ " parse trees" ^ wenzelm@42242: (if len <= limit then "" else " (" ^ string_of_int limit ^ " displayed)") ^ ":") :: wenzelm@42242: map (Pretty.string_of o Parser.pretty_parsetree) (take limit pts)))); wenzelm@42242: wenzelm@42242: val constrain_pos = not raw andalso Config.get ctxt Syntax.positions; wenzelm@42253: val parsetree_to_ast = parsetree_to_ast ctxt constrain_pos ast_tr; wenzelm@42242: in map parsetree_to_ast pts end; wenzelm@42242: wenzelm@42249: fun parse_raw ctxt root input = wenzelm@42242: let wenzelm@42253: val syn = ProofContext.syn_of ctxt; wenzelm@42253: val tr = Syntax.parse_translation syn; wenzelm@42255: val parse_rules = Syntax.parse_rules syn; wenzelm@42242: in wenzelm@42242: parse_asts ctxt false root input wenzelm@42255: |> (map o apsnd o Exn.maps_result) wenzelm@42255: (Ast.normalize ctxt parse_rules #> Exn.interruptible_capture (ast_to_term ctxt tr)) wenzelm@42242: end; wenzelm@42242: wenzelm@42242: wenzelm@42249: (* parse logical entities *) wenzelm@42242: wenzelm@42241: fun parse_failed ctxt pos msg kind = wenzelm@42241: cat_error msg ("Failed to parse " ^ kind ^ wenzelm@42241: Markup.markup Markup.report (Context_Position.reported_text ctxt pos Markup.bad "")); wenzelm@42241: wenzelm@42241: fun parse_sort ctxt text = wenzelm@42241: let wenzelm@42241: val (syms, pos) = Syntax.parse_token ctxt Markup.sort text; wenzelm@42249: val S = wenzelm@42249: parse_raw ctxt "sort" (syms, pos) wenzelm@42249: |> report_result ctxt pos wenzelm@42249: |> sort_of_term wenzelm@42242: handle ERROR msg => parse_failed ctxt pos msg "sort"; wenzelm@42241: in Type.minimize_sort (ProofContext.tsig_of ctxt) S end; wenzelm@42241: wenzelm@42241: fun parse_typ ctxt text = wenzelm@42241: let wenzelm@42241: val (syms, pos) = Syntax.parse_token ctxt Markup.typ text; wenzelm@42249: val T = wenzelm@42249: parse_raw ctxt "type" (syms, pos) wenzelm@42249: |> report_result ctxt pos wenzelm@42249: |> (fn t => typ_of_term (ProofContext.get_sort ctxt (term_sorts t)) t) wenzelm@42242: handle ERROR msg => parse_failed ctxt pos msg "type"; wenzelm@42241: in T end; wenzelm@42241: wenzelm@42281: fun parse_term is_prop ctxt text = wenzelm@42241: let wenzelm@42281: val (markup, kind, root, constrain) = wenzelm@42281: if is_prop wenzelm@42281: then (Markup.prop, "proposition", "prop", Type.constraint propT) wenzelm@42288: else (Markup.term, "term", Config.get ctxt Syntax.root, I); wenzelm@42241: val (syms, pos) = Syntax.parse_token ctxt markup text; wenzelm@42249: in wenzelm@42249: let wenzelm@42249: val results = parse_raw ctxt root (syms, pos) |> map (decode_term ctxt); wenzelm@42249: val ambiguity = length (proper_results results); wenzelm@42241: wenzelm@42249: val level = Config.get ctxt Syntax.ambiguity_level; wenzelm@42249: val limit = Config.get ctxt Syntax.ambiguity_limit; wenzelm@42249: wenzelm@42249: fun ambig_msg () = wenzelm@42249: if ambiguity > 1 andalso ambiguity <= level then wenzelm@42249: "Got more than one parse tree.\n\ wenzelm@42249: \Retry with smaller syntax_ambiguity_level for more information." wenzelm@42249: else ""; wenzelm@42249: wenzelm@42249: (*brute-force disambiguation via type-inference*) wenzelm@42281: fun check t = (Syntax.check_term ctxt (constrain t); Exn.Result t) wenzelm@42249: handle exn as ERROR _ => Exn.Exn exn; wenzelm@42249: wenzelm@42249: val results' = wenzelm@42249: if ambiguity > 1 then wenzelm@42249: (Par_List.map_name "Syntax_Phases.parse_term" o apsnd o Exn.maps_result) wenzelm@42249: check results wenzelm@42249: else results; wenzelm@42249: val reports' = fst (hd results'); wenzelm@42249: wenzelm@42249: val errs = map snd (failed_results results'); wenzelm@42249: val checked = map snd (proper_results results'); wenzelm@42249: val len = length checked; wenzelm@42249: wenzelm@42289: val show_term = Syntax.string_of_term (Config.put Printer.show_brackets true ctxt); wenzelm@42249: in wenzelm@42249: if len = 0 then wenzelm@42249: report_result ctxt pos wenzelm@42249: [(reports', Exn.Exn (Exn.EXCEPTIONS (ERROR (ambig_msg ()) :: errs)))] wenzelm@42249: else if len = 1 then wenzelm@42249: (if ambiguity > level then wenzelm@42249: Context_Position.if_visible ctxt warning wenzelm@42249: "Fortunately, only one parse tree is type correct.\n\ wenzelm@42249: \You may still want to disambiguate your grammar or your input." wenzelm@42249: else (); report_result ctxt pos results') wenzelm@42249: else wenzelm@42249: report_result ctxt pos wenzelm@42249: [(reports', Exn.Exn (ERROR (cat_lines (ambig_msg () :: wenzelm@42249: (("Ambiguous input, " ^ string_of_int len ^ " terms are type correct" ^ wenzelm@42249: (if len <= limit then "" else " (" ^ string_of_int limit ^ " displayed)") ^ ":") :: wenzelm@42249: map show_term (take limit checked))))))] wenzelm@42249: end handle ERROR msg => parse_failed ctxt pos msg kind wenzelm@42249: end; wenzelm@42241: wenzelm@42241: wenzelm@42242: (* parse_ast_pattern *) wenzelm@42242: wenzelm@42242: fun parse_ast_pattern ctxt (root, str) = wenzelm@42242: let wenzelm@42242: val syn = ProofContext.syn_of ctxt; wenzelm@42242: wenzelm@42242: fun constify (ast as Ast.Constant _) = ast wenzelm@42242: | constify (ast as Ast.Variable x) = wenzelm@42298: if is_some (Syntax.lookup_const syn x) orelse Long_Name.is_qualified x wenzelm@42298: then Ast.Constant x wenzelm@42242: else ast wenzelm@42242: | constify (Ast.Appl asts) = Ast.Appl (map constify asts); wenzelm@42242: wenzelm@42242: val (syms, pos) = Syntax.read_token str; wenzelm@42242: in wenzelm@42242: parse_asts ctxt true root (syms, pos) wenzelm@42242: |> report_result ctxt pos wenzelm@42242: |> constify wenzelm@42242: end; wenzelm@42242: wenzelm@42242: wenzelm@42242: wenzelm@42245: (** encode parse trees **) wenzelm@42245: wenzelm@42245: (* term_of_sort *) wenzelm@42245: wenzelm@42245: fun term_of_sort S = wenzelm@42245: let wenzelm@42245: val class = Lexicon.const o Lexicon.mark_class; wenzelm@42245: wenzelm@42245: fun classes [c] = class c wenzelm@42245: | classes (c :: cs) = Lexicon.const "_classes" $ class c $ classes cs; wenzelm@42245: in wenzelm@42245: (case S of wenzelm@42245: [] => Lexicon.const "_topsort" wenzelm@42245: | [c] => class c wenzelm@42245: | cs => Lexicon.const "_sort" $ classes cs) wenzelm@42245: end; wenzelm@42245: wenzelm@42245: wenzelm@42245: (* term_of_typ *) wenzelm@42245: wenzelm@42247: fun term_of_typ ctxt ty = wenzelm@42245: let wenzelm@42247: val show_sorts = Config.get ctxt show_sorts; wenzelm@42247: wenzelm@42245: fun of_sort t S = wenzelm@42245: if show_sorts then Lexicon.const "_ofsort" $ t $ term_of_sort S wenzelm@42245: else t; wenzelm@42245: wenzelm@42245: fun term_of (Type (a, Ts)) = wenzelm@42245: Term.list_comb (Lexicon.const (Lexicon.mark_type a), map term_of Ts) wenzelm@42245: | term_of (TFree (x, S)) = wenzelm@42290: if is_some (Term_Position.decode x) then Syntax.free x wenzelm@42290: else of_sort (Lexicon.const "_tfree" $ Syntax.free x) S wenzelm@42290: | term_of (TVar (xi, S)) = of_sort (Lexicon.const "_tvar" $ Syntax.var xi) S; wenzelm@42245: in term_of ty end; wenzelm@42245: wenzelm@42245: wenzelm@42245: (* simple_ast_of *) wenzelm@42245: wenzelm@42245: fun simple_ast_of ctxt = wenzelm@42245: let wenzelm@42245: val tune_var = if Config.get ctxt show_question_marks then I else unprefix "?"; wenzelm@42245: fun ast_of (Const (c, _)) = Ast.Constant c wenzelm@42245: | ast_of (Free (x, _)) = Ast.Variable x wenzelm@42245: | ast_of (Var (xi, _)) = Ast.Variable (tune_var (Term.string_of_vname xi)) wenzelm@42245: | ast_of (t as _ $ _) = wenzelm@42245: let val (f, args) = strip_comb t wenzelm@42245: in Ast.mk_appl (ast_of f) (map ast_of args) end wenzelm@42245: | ast_of (Bound i) = Ast.Variable ("B." ^ string_of_int i) wenzelm@42245: | ast_of (Abs _) = raise Fail "simple_ast_of: Abs"; wenzelm@42245: in ast_of end; wenzelm@42245: wenzelm@42245: wenzelm@42245: (* sort_to_ast and typ_to_ast *) wenzelm@42245: wenzelm@42245: fun ast_of_termT ctxt trf tm = wenzelm@42245: let wenzelm@42245: val ctxt' = Config.put show_sorts false ctxt; wenzelm@42245: fun ast_of (t as Const ("_tfree", _) $ Free _) = simple_ast_of ctxt t wenzelm@42245: | ast_of (t as Const ("_tvar", _) $ Var _) = simple_ast_of ctxt t wenzelm@42245: | ast_of (Const (a, _)) = trans a [] wenzelm@42245: | ast_of (t as _ $ _) = wenzelm@42245: (case strip_comb t of wenzelm@42245: (Const (a, _), args) => trans a args wenzelm@42245: | (f, args) => Ast.Appl (map ast_of (f :: args))) wenzelm@42245: | ast_of t = simple_ast_of ctxt t wenzelm@42254: and trans a args = ast_of (trf a ctxt' dummyT args) wenzelm@42254: handle Match => Ast.mk_appl (Ast.Constant a) (map ast_of args); wenzelm@42245: in ast_of tm end; wenzelm@42245: wenzelm@42245: fun sort_to_ast ctxt trf S = ast_of_termT ctxt trf (term_of_sort S); wenzelm@42247: fun typ_to_ast ctxt trf T = ast_of_termT ctxt trf (term_of_typ ctxt T); wenzelm@42245: wenzelm@42245: wenzelm@42245: (* term_to_ast *) wenzelm@42245: wenzelm@42252: fun term_to_ast idents is_syntax_const ctxt trf tm = wenzelm@42245: let wenzelm@42245: val show_types = wenzelm@42245: Config.get ctxt show_types orelse Config.get ctxt show_sorts orelse wenzelm@42245: Config.get ctxt show_all_types; wenzelm@42245: val show_structs = Config.get ctxt show_structs; wenzelm@42245: val show_free_types = Config.get ctxt show_free_types; wenzelm@42245: val show_all_types = Config.get ctxt show_all_types; wenzelm@42245: wenzelm@42245: val {structs, fixes} = idents; wenzelm@42245: wenzelm@42249: fun mark_atoms ((t as Const (c, _)) $ u) = wenzelm@42294: if member (op =) Syntax.token_markers c wenzelm@42245: then t $ u else mark_atoms t $ mark_atoms u wenzelm@42245: | mark_atoms (t $ u) = mark_atoms t $ mark_atoms u wenzelm@42245: | mark_atoms (Abs (x, T, t)) = Abs (x, T, mark_atoms t) wenzelm@42245: | mark_atoms (t as Const (c, T)) = wenzelm@42252: if is_syntax_const c then t wenzelm@42245: else Const (Lexicon.mark_const c, T) wenzelm@42245: | mark_atoms (t as Free (x, T)) = wenzelm@42245: let val i = find_index (fn s => s = x) structs + 1 in wenzelm@42245: if i = 0 andalso member (op =) fixes x then wenzelm@42245: Const (Lexicon.mark_fixed x, T) wenzelm@42245: else if i = 1 andalso not show_structs then wenzelm@42245: Lexicon.const "_struct" $ Lexicon.const "_indexdefault" wenzelm@42245: else Lexicon.const "_free" $ t wenzelm@42245: end wenzelm@42245: | mark_atoms (t as Var (xi, T)) = wenzelm@42288: if xi = Syntax_Ext.dddot_indexname then Const ("_DDDOT", T) wenzelm@42245: else Lexicon.const "_var" $ t wenzelm@42245: | mark_atoms a = a; wenzelm@42245: wenzelm@42245: fun prune_typs (t_seen as (Const _, _)) = t_seen wenzelm@42245: | prune_typs (t as Free (x, ty), seen) = wenzelm@42245: if ty = dummyT then (t, seen) wenzelm@42290: else if not show_free_types orelse member (op aconv) seen t then (Syntax.free x, seen) wenzelm@42245: else (t, t :: seen) wenzelm@42245: | prune_typs (t as Var (xi, ty), seen) = wenzelm@42245: if ty = dummyT then (t, seen) wenzelm@42290: else if not show_free_types orelse member (op aconv) seen t then (Syntax.var xi, seen) wenzelm@42245: else (t, t :: seen) wenzelm@42245: | prune_typs (t_seen as (Bound _, _)) = t_seen wenzelm@42245: | prune_typs (Abs (x, ty, t), seen) = wenzelm@42245: let val (t', seen') = prune_typs (t, seen); wenzelm@42245: in (Abs (x, ty, t'), seen') end wenzelm@42245: | prune_typs (t1 $ t2, seen) = wenzelm@42245: let wenzelm@42245: val (t1', seen') = prune_typs (t1, seen); wenzelm@42245: val (t2', seen'') = prune_typs (t2, seen'); wenzelm@42245: in (t1' $ t2', seen'') end; wenzelm@42245: wenzelm@42245: fun ast_of tm = wenzelm@42245: (case strip_comb tm of wenzelm@42284: (t as Abs _, ts) => Ast.mk_appl (ast_of (Syntax_Trans.abs_tr' ctxt t)) (map ast_of ts) wenzelm@42245: | ((c as Const ("_free", _)), Free (x, T) :: ts) => wenzelm@42290: Ast.mk_appl (constrain (c $ Syntax.free x) T) (map ast_of ts) wenzelm@42245: | ((c as Const ("_var", _)), Var (xi, T) :: ts) => wenzelm@42290: Ast.mk_appl (constrain (c $ Syntax.var xi) T) (map ast_of ts) wenzelm@42245: | ((c as Const ("_bound", _)), Free (x, T) :: ts) => wenzelm@42290: Ast.mk_appl (constrain (c $ Syntax.free x) T) (map ast_of ts) wenzelm@42245: | (Const ("_idtdummy", T), ts) => wenzelm@42245: Ast.mk_appl (constrain (Lexicon.const "_idtdummy") T) (map ast_of ts) wenzelm@42245: | (const as Const (c, T), ts) => wenzelm@42245: if show_all_types wenzelm@42245: then Ast.mk_appl (constrain const T) (map ast_of ts) wenzelm@42245: else trans c T ts wenzelm@42245: | (t, ts) => Ast.mk_appl (simple_ast_of ctxt t) (map ast_of ts)) wenzelm@42245: wenzelm@42254: and trans a T args = ast_of (trf a ctxt T args) wenzelm@42254: handle Match => Ast.mk_appl (Ast.Constant a) (map ast_of args) wenzelm@42245: wenzelm@42245: and constrain t T = wenzelm@42245: if show_types andalso T <> dummyT then wenzelm@42248: Ast.Appl [Ast.Constant "_constrain", simple_ast_of ctxt t, wenzelm@42247: ast_of_termT ctxt trf (term_of_typ ctxt T)] wenzelm@42245: else simple_ast_of ctxt t; wenzelm@42245: in wenzelm@42245: tm wenzelm@42284: |> Syntax_Trans.prop_tr' wenzelm@42245: |> show_types ? (#1 o prune_typs o rpair []) wenzelm@42245: |> mark_atoms wenzelm@42245: |> ast_of wenzelm@42245: end; wenzelm@42245: wenzelm@42245: wenzelm@42245: wenzelm@42242: (** unparse **) wenzelm@42242: wenzelm@42245: local wenzelm@42245: wenzelm@42267: fun free_or_skolem ctxt x = wenzelm@42267: let wenzelm@42267: val m = wenzelm@42267: if Variable.is_fixed ctxt x orelse Syntax.is_pretty_global ctxt wenzelm@42267: then Markup.fixed x wenzelm@42267: else Markup.hilite; wenzelm@42267: in wenzelm@42267: if can Name.dest_skolem x wenzelm@42267: then ([m, Markup.skolem], ProofContext.revert_skolem ctxt x) wenzelm@42267: else ([m, Markup.free], x) wenzelm@42267: end; wenzelm@42267: wenzelm@42267: fun var_or_skolem s = wenzelm@42267: (case Lexicon.read_variable s of wenzelm@42267: SOME (x, i) => wenzelm@42267: (case try Name.dest_skolem x of wenzelm@42267: NONE => (Markup.var, s) wenzelm@42267: | SOME x' => (Markup.skolem, Term.string_of_vname (x', i))) wenzelm@42267: | NONE => (Markup.var, s)); wenzelm@42267: wenzelm@42267: fun unparse_t t_to_ast prt_t markup ctxt t = wenzelm@42245: let wenzelm@42253: val syn = ProofContext.syn_of ctxt; wenzelm@42267: wenzelm@42267: fun token_trans "_tfree" x = SOME (Pretty.mark_str (Markup.tfree, x)) wenzelm@42267: | token_trans "_tvar" x = SOME (Pretty.mark_str (Markup.tvar, x)) wenzelm@42267: | token_trans "_free" x = SOME (Pretty.marks_str (free_or_skolem ctxt x)) wenzelm@42267: | token_trans "_bound" x = SOME (Pretty.mark_str (Markup.bound, x)) wenzelm@42267: | token_trans "_var" x = SOME (Pretty.mark_str (var_or_skolem x)) wenzelm@42267: | token_trans "_numeral" x = SOME (Pretty.mark_str (Markup.numeral, x)) wenzelm@42267: | token_trans "_inner_string" x = SOME (Pretty.mark_str (Markup.inner_string, x)) wenzelm@42267: | token_trans _ _ = NONE; wenzelm@42267: wenzelm@42301: fun markup_extern c = wenzelm@42301: (case Syntax.lookup_const syn c of wenzelm@42301: SOME "" => ([], c) wenzelm@42301: | SOME b => markup_extern b wenzelm@42301: | NONE => c |> Lexicon.unmark wenzelm@42359: {case_class = fn x => ([Markup.tclass x], ProofContext.extern_class ctxt x), wenzelm@42359: case_type = fn x => ([Markup.tycon x], ProofContext.extern_type ctxt x), wenzelm@42359: case_const = fn x => ([Markup.const x], ProofContext.extern_const ctxt x), wenzelm@42301: case_fixed = fn x => free_or_skolem ctxt x, wenzelm@42301: case_default = fn x => ([], x)}); wenzelm@42245: in wenzelm@42255: t_to_ast ctxt (Syntax.print_translation syn) t wenzelm@42255: |> Ast.normalize ctxt (Syntax.print_rules syn) wenzelm@42267: |> prt_t ctxt (Syntax.prtabs syn) (Syntax.print_ast_translation syn) token_trans markup_extern wenzelm@42253: |> Pretty.markup markup wenzelm@42245: end; wenzelm@42245: wenzelm@42245: in wenzelm@42245: wenzelm@42267: val unparse_sort = unparse_t sort_to_ast Printer.pretty_typ_ast Markup.sort; wenzelm@42267: val unparse_typ = unparse_t typ_to_ast Printer.pretty_typ_ast Markup.typ; wenzelm@42241: wenzelm@42241: fun unparse_term ctxt = wenzelm@42241: let wenzelm@42252: val thy = ProofContext.theory_of ctxt; wenzelm@42252: val syn = ProofContext.syn_of ctxt; wenzelm@42252: val idents = Local_Syntax.idents_of (ProofContext.syntax_of ctxt); wenzelm@42241: in wenzelm@42298: unparse_t (term_to_ast idents (is_some o Syntax.lookup_const syn)) wenzelm@42267: (Printer.pretty_term_ast (not (Pure_Thy.old_appl_syntax thy))) wenzelm@42267: Markup.term ctxt wenzelm@42241: end; wenzelm@42241: wenzelm@42249: end; wenzelm@42249: wenzelm@42241: wenzelm@42245: wenzelm@42245: (** translations **) wenzelm@42245: wenzelm@42245: (* type propositions *) wenzelm@42245: wenzelm@42247: fun type_prop_tr' ctxt T [Const ("\\<^const>Pure.sort_constraint", _)] = wenzelm@42247: Lexicon.const "_sort_constraint" $ term_of_typ (Config.put show_sorts true ctxt) T wenzelm@42247: | type_prop_tr' ctxt T [t] = wenzelm@42247: Lexicon.const "_ofclass" $ term_of_typ ctxt T $ t wenzelm@42245: | type_prop_tr' _ T ts = raise TYPE ("type_prop_tr'", [T], ts); wenzelm@42245: wenzelm@42245: wenzelm@42245: (* type reflection *) wenzelm@42245: wenzelm@42247: fun type_tr' ctxt (Type ("itself", [T])) ts = wenzelm@42247: Term.list_comb (Lexicon.const "_TYPE" $ term_of_typ ctxt T, ts) wenzelm@42245: | type_tr' _ _ _ = raise Match; wenzelm@42245: wenzelm@42245: wenzelm@42245: (* type constraints *) wenzelm@42245: wenzelm@42247: fun type_constraint_tr' ctxt (Type ("fun", [T, _])) (t :: ts) = wenzelm@42248: Term.list_comb (Lexicon.const "_constrain" $ t $ term_of_typ ctxt T, ts) wenzelm@42245: | type_constraint_tr' _ _ _ = raise Match; wenzelm@42245: wenzelm@42245: wenzelm@42295: (* authentic syntax *) wenzelm@42295: wenzelm@42295: fun const_ast_tr intern ctxt [Ast.Variable c] = wenzelm@42295: let wenzelm@42295: val Const (c', _) = ProofContext.read_const_proper ctxt false c; wenzelm@42295: val d = if intern then Lexicon.mark_const c' else c; wenzelm@42295: in Ast.Constant d end wenzelm@42296: | const_ast_tr intern ctxt [Ast.Appl [Ast.Constant "_constrain", x, T]] = wenzelm@42296: Ast.Appl [Ast.Constant "_constrain", const_ast_tr intern ctxt [x], T] wenzelm@42295: | const_ast_tr _ _ asts = raise Ast.AST ("const_ast_tr", asts); wenzelm@42295: wenzelm@42295: wenzelm@42245: (* setup translations *) wenzelm@42245: wenzelm@42245: val _ = Context.>> (Context.map_theory wenzelm@42295: (Sign.add_advanced_trfuns wenzelm@42295: ([("_context_const", const_ast_tr true), wenzelm@42295: ("_context_xconst", const_ast_tr false)], [], [], []) #> wenzelm@42295: Sign.add_advanced_trfunsT wenzelm@42245: [("_type_prop", type_prop_tr'), wenzelm@42245: ("\\<^const>TYPE", type_tr'), wenzelm@42245: ("_type_constraint_", type_constraint_tr')])); wenzelm@42245: wenzelm@42245: wenzelm@42245: wenzelm@42242: (** install operations **) wenzelm@42242: wenzelm@42241: val _ = Syntax.install_operations wenzelm@42241: {parse_sort = parse_sort, wenzelm@42241: parse_typ = parse_typ, wenzelm@42281: parse_term = parse_term false, wenzelm@42281: parse_prop = parse_term true, wenzelm@42241: unparse_sort = unparse_sort, wenzelm@42241: unparse_typ = unparse_typ, wenzelm@42241: unparse_term = unparse_term}; wenzelm@42241: wenzelm@42241: end;