4 Generated source files for other languages: with antiquotations, without Isabelle symbols. |
4 Generated source files for other languages: with antiquotations, without Isabelle symbols. |
5 *) |
5 *) |
6 |
6 |
7 signature GENERATED_FILES = |
7 signature GENERATED_FILES = |
8 sig |
8 sig |
|
9 val add_files: (Path.T * Position.T) * string -> theory -> theory |
|
10 val get_files: theory -> (Path.T * string) list |
|
11 val write_files: theory -> Path.T -> Path.T list |
9 type file_type = |
12 type file_type = |
10 {name: string, ext: string, make_comment: string -> string, make_string: string -> string} |
13 {name: string, ext: string, make_comment: string -> string, make_string: string -> string} |
11 val file_type: |
14 val file_type: |
12 binding -> {ext: string, make_comment: string -> string, make_string: string -> string} -> |
15 binding -> {ext: string, make_comment: string -> string, make_string: string -> string} -> |
13 theory -> theory |
16 theory -> theory |
14 val antiquotation: binding -> 'a Token.context_parser -> |
17 val antiquotation: binding -> 'a Token.context_parser -> |
15 ({context: Proof.context, source: Token.src, file_type: file_type, argument: 'a} -> string) -> |
18 ({context: Proof.context, source: Token.src, file_type: file_type, argument: 'a} -> string) -> |
16 theory -> theory |
19 theory -> theory |
17 val set_string: string -> Proof.context -> Proof.context |
20 val set_string: string -> Proof.context -> Proof.context |
18 val generate_file_cmd: (string * Position.T) * Input.source -> local_theory -> local_theory |
21 val generate_file_cmd: (string * Position.T) * Input.source -> local_theory -> local_theory |
19 val write: theory -> Path.T -> Path.T list |
|
20 val export: theory -> string -> Path.T list |
|
21 end; |
22 end; |
22 |
23 |
23 structure Generated_Files: GENERATED_FILES = |
24 structure Generated_Files: GENERATED_FILES = |
24 struct |
25 struct |
25 |
26 |
31 type antiquotation = Token.src -> Proof.context -> file_type -> string; |
32 type antiquotation = Token.src -> Proof.context -> file_type -> string; |
32 |
33 |
33 structure Data = Theory_Data |
34 structure Data = Theory_Data |
34 ( |
35 ( |
35 type T = |
36 type T = |
|
37 (Path.T * (Position.T * string)) list * (*files for current theory*) |
36 file_type Name_Space.table * (*file types*) |
38 file_type Name_Space.table * (*file types*) |
37 antiquotation Name_Space.table * (*antiquotations*) |
39 antiquotation Name_Space.table; (*antiquotations*) |
38 (Path.T * (Position.T * string)) list; (*generated files for current theory*) |
|
39 val empty = |
40 val empty = |
40 (Name_Space.empty_table Markup.file_typeN, |
41 ([], |
41 Name_Space.empty_table Markup.antiquotationN, |
42 Name_Space.empty_table Markup.file_typeN, |
42 []); |
43 Name_Space.empty_table Markup.antiquotationN); |
43 val extend = @{apply 3(3)} (K []); |
44 val extend = @{apply 3(1)} (K []); |
44 fun merge ((types1, antiqs1, _), (types2, antiqs2, _)) = |
45 fun merge ((_, types1, antiqs1), (_, types2, antiqs2)) = |
45 (Name_Space.merge_tables (types1, types2), |
46 ([], |
46 Name_Space.merge_tables (antiqs1, antiqs2), |
47 Name_Space.merge_tables (types1, types2), |
47 []); |
48 Name_Space.merge_tables (antiqs1, antiqs2)); |
48 ); |
49 ); |
49 |
50 |
50 val get_files = rev o #3 o Data.get; |
51 |
51 |
52 (* files *) |
52 fun add_files (path, (pos, text)) = |
53 |
53 (Data.map o @{apply 3(3)}) (fn files => |
54 fun add_files ((path0, pos), text) = |
54 (case AList.lookup (op =) files path of |
55 let |
55 SOME (pos', _) => |
56 val path = Path.expand path0; |
56 error ("Duplicate generated file " ^ Path.print path ^ Position.here_list [pos, pos']) |
57 fun err msg ps = error (msg ^ ": " ^ Path.print path ^ Position.here_list ps); |
57 | NONE => (path, (pos, text)) :: files)); |
58 val _ = |
|
59 if Path.is_absolute path then err "Illegal absolute path" [pos] |
|
60 else if Path.has_parent path then err "Illegal parent path" [pos] |
|
61 else (); |
|
62 in |
|
63 (Data.map o @{apply 3(1)}) (fn files => |
|
64 (case AList.lookup (op =) files path of |
|
65 SOME (pos', _) => err "Duplicate generated file" [pos, pos'] |
|
66 | NONE => (path, (pos, text)) :: files)) |
|
67 end; |
|
68 |
|
69 val get_files = map (apsnd #2) o rev o #1 o Data.get; |
|
70 |
|
71 fun write_files thy dir = |
|
72 get_files thy |> map (fn (path, text) => |
|
73 let |
|
74 val path' = Path.expand (Path.append dir path); |
|
75 val _ = Isabelle_System.mkdirs (Path.dir path'); |
|
76 val _ = File.generate path' text; |
|
77 in path end); |
58 |
78 |
59 |
79 |
60 (* file types *) |
80 (* file types *) |
61 |
81 |
62 fun the_file_type thy ext = |
82 fun the_file_type thy ext = |
63 if ext = "" then error "Bad file extension" |
83 if ext = "" then error "Bad file extension" |
64 else |
84 else |
65 (#1 (Data.get thy), NONE) |-> Name_Space.fold_table |
85 (#2 (Data.get thy), NONE) |-> Name_Space.fold_table |
66 (fn (_, file_type) => fn res => |
86 (fn (_, file_type) => fn res => |
67 if #ext file_type = ext then SOME file_type else res) |
87 if #ext file_type = ext then SOME file_type else res) |
68 |> (fn SOME file_type => file_type |
88 |> (fn SOME file_type => file_type |
69 | NONE => error ("Unknown file type for extension " ^ quote ext)); |
89 | NONE => error ("Unknown file type for extension " ^ quote ext)); |
70 |
90 |
72 let |
92 let |
73 val name = Binding.name_of binding; |
93 val name = Binding.name_of binding; |
74 val pos = Binding.pos_of binding; |
94 val pos = Binding.pos_of binding; |
75 val file_type = {name = name, ext = ext, make_comment = make_comment, make_string = make_string}; |
95 val file_type = {name = name, ext = ext, make_comment = make_comment, make_string = make_string}; |
76 |
96 |
77 val table = #1 (Data.get thy); |
97 val table = #2 (Data.get thy); |
78 val space = Name_Space.space_of_table table; |
98 val space = Name_Space.space_of_table table; |
79 val context = Context.Theory thy |> Name_Space.map_naming (K Name_Space.global_naming); |
99 val context = Context.Theory thy |> Name_Space.map_naming (K Name_Space.global_naming); |
80 val (_, data') = table |> Name_Space.define context true (Binding.make (name, pos), file_type); |
100 val (_, data') = table |> Name_Space.define context true (Binding.make (name, pos), file_type); |
81 |
101 |
82 val _ = |
102 val _ = |
83 (case try (#name o the_file_type thy) ext of |
103 (case try (#name o the_file_type thy) ext of |
84 NONE => () |
104 NONE => () |
85 | SOME name' => |
105 | SOME name' => |
86 error ("Extension " ^ quote ext ^ " already registered for file type " ^ |
106 error ("Extension " ^ quote ext ^ " already registered for file type " ^ |
87 quote (Markup.markup (Name_Space.markup space name') name') ^ Position.here pos)); |
107 quote (Markup.markup (Name_Space.markup space name') name') ^ Position.here pos)); |
88 in thy |> (Data.map o @{apply 3(1)}) (K data') end; |
108 in thy |> (Data.map o @{apply 3(2)}) (K data') end; |
89 |
109 |
90 |
110 |
91 (* antiquotations *) |
111 (* antiquotations *) |
92 |
112 |
93 val get_antiquotations = #2 o Data.get o Proof_Context.theory_of; |
113 val get_antiquotations = #3 o Data.get o Proof_Context.theory_of; |
94 |
114 |
95 fun antiquotation name scan body thy = |
115 fun antiquotation name scan body thy = |
96 let |
116 let |
97 fun ant src ctxt file_type : string = |
117 fun ant src ctxt file_type : string = |
98 let val (x, ctxt') = Token.syntax scan src ctxt |
118 let val (x, ctxt') = Token.syntax scan src ctxt |
99 in body {context = ctxt', source = src, file_type = file_type, argument = x} end; |
119 in body {context = ctxt', source = src, file_type = file_type, argument = x} end; |
100 in |
120 in |
101 thy |
121 thy |
102 |> (Data.map o @{apply 3(2)}) (Name_Space.define (Context.Theory thy) true (name, ant) #> #2) |
122 |> (Data.map o @{apply 3(3)}) (Name_Space.define (Context.Theory thy) true (name, ant) #> #2) |
103 end; |
123 end; |
104 |
124 |
105 val scan_antiq = |
125 val scan_antiq = |
106 Antiquote.scan_control >> Antiquote.Control || |
126 Antiquote.scan_control >> Antiquote.Control || |
107 Scan.one (Symbol.not_eof o Symbol_Pos.symbol) >> (Antiquote.Text o Symbol_Pos.symbol); |
127 Scan.one (Symbol.not_eof o Symbol_Pos.symbol) >> (Antiquote.Text o Symbol_Pos.symbol); |
136 |
156 |
137 fun generate_file_cmd ((file, pos), source) lthy = |
157 fun generate_file_cmd ((file, pos), source) lthy = |
138 let |
158 let |
139 val thy = Proof_Context.theory_of lthy; |
159 val thy = Proof_Context.theory_of lthy; |
140 |
160 |
141 val path = Path.expand (Path.explode file); |
161 val path = Path.explode file; |
142 fun err_path msg = error (msg ^ ": " ^ Path.print path ^ Position.here pos); |
|
143 val _ = |
|
144 if Path.is_absolute path then err_path "Illegal absolute path" |
|
145 else if Path.has_parent path then err_path "Illegal parent path" |
|
146 else (); |
|
147 |
|
148 val file_type = |
162 val file_type = |
149 the_file_type thy (#2 (Path.split_ext path)) |
163 the_file_type thy (#2 (Path.split_ext path)) |
150 handle ERROR msg => error (msg ^ Position.here pos); |
164 handle ERROR msg => error (msg ^ Position.here pos); |
151 |
165 |
152 val header = #make_comment file_type " generated by Isabelle "; |
166 val header = #make_comment file_type " generated by Isabelle "; |
153 val text = header ^ "\n" ^ read_source lthy file_type source; |
167 val text = header ^ "\n" ^ read_source lthy file_type source; |
154 in lthy |> (Local_Theory.background_theory o add_files) (path, (pos, text)) end; |
168 in lthy |> (Local_Theory.background_theory o add_files) ((path, pos), text) end; |
155 |
|
156 fun write thy dir = |
|
157 get_files thy |> map (fn (path, (_, text)) => |
|
158 let |
|
159 val path' = Path.expand (Path.append dir path); |
|
160 val _ = Isabelle_System.mkdirs (Path.dir path'); |
|
161 val _ = File.generate path' text; |
|
162 in path end); |
|
163 |
|
164 fun export thy prefix = |
|
165 get_files thy |> map (fn (path, (_, text)) => |
|
166 let |
|
167 val name = (if prefix = "" then "" else prefix ^ "/") ^ Path.implode path; |
|
168 val _ = Export.export thy name [text]; |
|
169 in path end); |
|
170 |
169 |
171 |
170 |
172 |
171 |
173 (** concrete file types **) |
172 (** concrete file types **) |
174 |
173 |