author | blanchet |
Mon, 07 Jan 2013 19:15:01 +0100 | |
changeset 50758 | 26936f4ae087 |
parent 45778 | df6e210fb44c |
child 72004 | 913162a47d9f |
permissions | -rw-r--r-- |
39348 | 1 |
(* ========================================================================= *) |
2 |
(* FIRST ORDER LOGIC TERMS *) |
|
39502 | 3 |
(* Copyright (c) 2001 Joe Hurd, distributed under the BSD License *) |
39348 | 4 |
(* ========================================================================= *) |
5 |
||
6 |
structure Term :> Term = |
|
7 |
struct |
|
8 |
||
9 |
open Useful; |
|
10 |
||
11 |
(* ------------------------------------------------------------------------- *) |
|
12 |
(* A type of first order logic terms. *) |
|
13 |
(* ------------------------------------------------------------------------- *) |
|
14 |
||
15 |
type var = Name.name; |
|
16 |
||
17 |
type functionName = Name.name; |
|
18 |
||
19 |
type function = functionName * int; |
|
20 |
||
21 |
type const = functionName; |
|
22 |
||
23 |
datatype term = |
|
24 |
Var of Name.name |
|
25 |
| Fn of Name.name * term list; |
|
26 |
||
27 |
(* ------------------------------------------------------------------------- *) |
|
28 |
(* Constructors and destructors. *) |
|
29 |
(* ------------------------------------------------------------------------- *) |
|
30 |
||
31 |
(* Variables *) |
|
32 |
||
33 |
fun destVar (Var v) = v |
|
34 |
| destVar (Fn _) = raise Error "destVar"; |
|
35 |
||
36 |
val isVar = can destVar; |
|
37 |
||
38 |
fun equalVar v (Var v') = Name.equal v v' |
|
39 |
| equalVar _ _ = false; |
|
40 |
||
41 |
(* Functions *) |
|
42 |
||
43 |
fun destFn (Fn f) = f |
|
44 |
| destFn (Var _) = raise Error "destFn"; |
|
45 |
||
46 |
val isFn = can destFn; |
|
47 |
||
48 |
fun fnName tm = fst (destFn tm); |
|
49 |
||
50 |
fun fnArguments tm = snd (destFn tm); |
|
51 |
||
52 |
fun fnArity tm = length (fnArguments tm); |
|
53 |
||
54 |
fun fnFunction tm = (fnName tm, fnArity tm); |
|
55 |
||
56 |
local |
|
57 |
fun func fs [] = fs |
|
58 |
| func fs (Var _ :: tms) = func fs tms |
|
59 |
| func fs (Fn (n,l) :: tms) = |
|
60 |
func (NameAritySet.add fs (n, length l)) (l @ tms); |
|
61 |
in |
|
62 |
fun functions tm = func NameAritySet.empty [tm]; |
|
63 |
end; |
|
64 |
||
65 |
local |
|
66 |
fun func fs [] = fs |
|
67 |
| func fs (Var _ :: tms) = func fs tms |
|
68 |
| func fs (Fn (n,l) :: tms) = func (NameSet.add fs n) (l @ tms); |
|
69 |
in |
|
70 |
fun functionNames tm = func NameSet.empty [tm]; |
|
71 |
end; |
|
72 |
||
73 |
(* Constants *) |
|
74 |
||
75 |
fun mkConst c = (Fn (c, [])); |
|
76 |
||
77 |
fun destConst (Fn (c, [])) = c |
|
78 |
| destConst _ = raise Error "destConst"; |
|
79 |
||
80 |
val isConst = can destConst; |
|
81 |
||
82 |
(* Binary functions *) |
|
83 |
||
84 |
fun mkBinop f (a,b) = Fn (f,[a,b]); |
|
85 |
||
86 |
fun destBinop f (Fn (x,[a,b])) = |
|
87 |
if Name.equal x f then (a,b) else raise Error "Term.destBinop: wrong binop" |
|
88 |
| destBinop _ _ = raise Error "Term.destBinop: not a binop"; |
|
89 |
||
90 |
fun isBinop f = can (destBinop f); |
|
91 |
||
92 |
(* ------------------------------------------------------------------------- *) |
|
93 |
(* The size of a term in symbols. *) |
|
94 |
(* ------------------------------------------------------------------------- *) |
|
95 |
||
96 |
val VAR_SYMBOLS = 1; |
|
97 |
||
98 |
val FN_SYMBOLS = 1; |
|
99 |
||
100 |
local |
|
101 |
fun sz n [] = n |
|
102 |
| sz n (Var _ :: tms) = sz (n + VAR_SYMBOLS) tms |
|
103 |
| sz n (Fn (func,args) :: tms) = sz (n + FN_SYMBOLS) (args @ tms); |
|
104 |
in |
|
105 |
fun symbols tm = sz 0 [tm]; |
|
106 |
end; |
|
107 |
||
108 |
(* ------------------------------------------------------------------------- *) |
|
109 |
(* A total comparison function for terms. *) |
|
110 |
(* ------------------------------------------------------------------------- *) |
|
111 |
||
112 |
local |
|
113 |
fun cmp [] [] = EQUAL |
|
114 |
| cmp (tm1 :: tms1) (tm2 :: tms2) = |
|
115 |
let |
|
116 |
val tm1_tm2 = (tm1,tm2) |
|
117 |
in |
|
118 |
if Portable.pointerEqual tm1_tm2 then cmp tms1 tms2 |
|
119 |
else |
|
120 |
case tm1_tm2 of |
|
121 |
(Var v1, Var v2) => |
|
122 |
(case Name.compare (v1,v2) of |
|
123 |
LESS => LESS |
|
124 |
| EQUAL => cmp tms1 tms2 |
|
125 |
| GREATER => GREATER) |
|
126 |
| (Var _, Fn _) => LESS |
|
127 |
| (Fn _, Var _) => GREATER |
|
128 |
| (Fn (f1,a1), Fn (f2,a2)) => |
|
129 |
(case Name.compare (f1,f2) of |
|
130 |
LESS => LESS |
|
131 |
| EQUAL => |
|
132 |
(case Int.compare (length a1, length a2) of |
|
133 |
LESS => LESS |
|
134 |
| EQUAL => cmp (a1 @ tms1) (a2 @ tms2) |
|
135 |
| GREATER => GREATER) |
|
136 |
| GREATER => GREATER) |
|
137 |
end |
|
138 |
| cmp _ _ = raise Bug "Term.compare"; |
|
139 |
in |
|
140 |
fun compare (tm1,tm2) = cmp [tm1] [tm2]; |
|
141 |
end; |
|
142 |
||
143 |
fun equal tm1 tm2 = compare (tm1,tm2) = EQUAL; |
|
144 |
||
145 |
(* ------------------------------------------------------------------------- *) |
|
146 |
(* Subterms. *) |
|
147 |
(* ------------------------------------------------------------------------- *) |
|
148 |
||
149 |
type path = int list; |
|
150 |
||
151 |
fun subterm tm [] = tm |
|
152 |
| subterm (Var _) (_ :: _) = raise Error "Term.subterm: Var" |
|
153 |
| subterm (Fn (_,tms)) (h :: t) = |
|
154 |
if h >= length tms then raise Error "Term.replace: Fn" |
|
155 |
else subterm (List.nth (tms,h)) t; |
|
156 |
||
157 |
local |
|
158 |
fun subtms [] acc = acc |
|
159 |
| subtms ((path,tm) :: rest) acc = |
|
160 |
let |
|
161 |
fun f (n,arg) = (n :: path, arg) |
|
162 |
||
45778 | 163 |
val acc = (List.rev path, tm) :: acc |
39348 | 164 |
in |
165 |
case tm of |
|
166 |
Var _ => subtms rest acc |
|
42102 | 167 |
| Fn (_,args) => subtms (List.map f (enumerate args) @ rest) acc |
39348 | 168 |
end; |
169 |
in |
|
170 |
fun subterms tm = subtms [([],tm)] []; |
|
171 |
end; |
|
172 |
||
173 |
fun replace tm ([],res) = if equal res tm then tm else res |
|
174 |
| replace tm (h :: t, res) = |
|
175 |
case tm of |
|
176 |
Var _ => raise Error "Term.replace: Var" |
|
177 |
| Fn (func,tms) => |
|
178 |
if h >= length tms then raise Error "Term.replace: Fn" |
|
179 |
else |
|
180 |
let |
|
181 |
val arg = List.nth (tms,h) |
|
182 |
val arg' = replace arg (t,res) |
|
183 |
in |
|
184 |
if Portable.pointerEqual (arg',arg) then tm |
|
185 |
else Fn (func, updateNth (h,arg') tms) |
|
186 |
end; |
|
187 |
||
188 |
fun find pred = |
|
189 |
let |
|
190 |
fun search [] = NONE |
|
191 |
| search ((path,tm) :: rest) = |
|
45778 | 192 |
if pred tm then SOME (List.rev path) |
39348 | 193 |
else |
194 |
case tm of |
|
195 |
Var _ => search rest |
|
196 |
| Fn (_,a) => |
|
197 |
let |
|
42102 | 198 |
val subtms = List.map (fn (i,t) => (i :: path, t)) (enumerate a) |
39348 | 199 |
in |
200 |
search (subtms @ rest) |
|
201 |
end |
|
202 |
in |
|
203 |
fn tm => search [([],tm)] |
|
204 |
end; |
|
205 |
||
206 |
val ppPath = Print.ppList Print.ppInt; |
|
207 |
||
208 |
val pathToString = Print.toString ppPath; |
|
209 |
||
210 |
(* ------------------------------------------------------------------------- *) |
|
211 |
(* Free variables. *) |
|
212 |
(* ------------------------------------------------------------------------- *) |
|
213 |
||
214 |
local |
|
215 |
fun free _ [] = false |
|
216 |
| free v (Var w :: tms) = Name.equal v w orelse free v tms |
|
217 |
| free v (Fn (_,args) :: tms) = free v (args @ tms); |
|
218 |
in |
|
219 |
fun freeIn v tm = free v [tm]; |
|
220 |
end; |
|
221 |
||
222 |
local |
|
223 |
fun free vs [] = vs |
|
224 |
| free vs (Var v :: tms) = free (NameSet.add vs v) tms |
|
225 |
| free vs (Fn (_,args) :: tms) = free vs (args @ tms); |
|
226 |
in |
|
227 |
val freeVarsList = free NameSet.empty; |
|
228 |
||
229 |
fun freeVars tm = freeVarsList [tm]; |
|
230 |
end; |
|
231 |
||
232 |
(* ------------------------------------------------------------------------- *) |
|
233 |
(* Fresh variables. *) |
|
234 |
(* ------------------------------------------------------------------------- *) |
|
235 |
||
236 |
fun newVar () = Var (Name.newName ()); |
|
237 |
||
42102 | 238 |
fun newVars n = List.map Var (Name.newNames n); |
39348 | 239 |
|
240 |
local |
|
42102 | 241 |
fun avoid av n = NameSet.member n av; |
39348 | 242 |
in |
42102 | 243 |
fun variantPrime av = Name.variantPrime {avoid = avoid av}; |
39348 | 244 |
|
42102 | 245 |
fun variantNum av = Name.variantNum {avoid = avoid av}; |
39348 | 246 |
end; |
247 |
||
248 |
(* ------------------------------------------------------------------------- *) |
|
249 |
(* Special support for terms with type annotations. *) |
|
250 |
(* ------------------------------------------------------------------------- *) |
|
251 |
||
252 |
val hasTypeFunctionName = Name.fromString ":"; |
|
253 |
||
254 |
val hasTypeFunction = (hasTypeFunctionName,2); |
|
255 |
||
256 |
fun destFnHasType ((f,a) : functionName * term list) = |
|
257 |
if not (Name.equal f hasTypeFunctionName) then |
|
258 |
raise Error "Term.destFnHasType" |
|
259 |
else |
|
260 |
case a of |
|
261 |
[tm,ty] => (tm,ty) |
|
262 |
| _ => raise Error "Term.destFnHasType"; |
|
263 |
||
264 |
val isFnHasType = can destFnHasType; |
|
265 |
||
266 |
fun isTypedVar tm = |
|
267 |
case tm of |
|
268 |
Var _ => true |
|
269 |
| Fn func => |
|
270 |
case total destFnHasType func of |
|
271 |
SOME (Var _, _) => true |
|
272 |
| _ => false; |
|
273 |
||
274 |
local |
|
275 |
fun sz n [] = n |
|
276 |
| sz n (tm :: tms) = |
|
277 |
case tm of |
|
278 |
Var _ => sz (n + 1) tms |
|
279 |
| Fn func => |
|
280 |
case total destFnHasType func of |
|
281 |
SOME (tm,_) => sz n (tm :: tms) |
|
282 |
| NONE => |
|
283 |
let |
|
284 |
val (_,a) = func |
|
285 |
in |
|
286 |
sz (n + 1) (a @ tms) |
|
287 |
end; |
|
288 |
in |
|
289 |
fun typedSymbols tm = sz 0 [tm]; |
|
290 |
end; |
|
291 |
||
292 |
local |
|
293 |
fun subtms [] acc = acc |
|
294 |
| subtms ((path,tm) :: rest) acc = |
|
295 |
case tm of |
|
296 |
Var _ => subtms rest acc |
|
297 |
| Fn func => |
|
298 |
case total destFnHasType func of |
|
299 |
SOME (t,_) => |
|
300 |
(case t of |
|
301 |
Var _ => subtms rest acc |
|
302 |
| Fn _ => |
|
303 |
let |
|
45778 | 304 |
val acc = (List.rev path, tm) :: acc |
39348 | 305 |
val rest = (0 :: path, t) :: rest |
306 |
in |
|
307 |
subtms rest acc |
|
308 |
end) |
|
309 |
| NONE => |
|
310 |
let |
|
311 |
fun f (n,arg) = (n :: path, arg) |
|
312 |
||
313 |
val (_,args) = func |
|
314 |
||
45778 | 315 |
val acc = (List.rev path, tm) :: acc |
39348 | 316 |
|
42102 | 317 |
val rest = List.map f (enumerate args) @ rest |
39348 | 318 |
in |
319 |
subtms rest acc |
|
320 |
end; |
|
321 |
in |
|
322 |
fun nonVarTypedSubterms tm = subtms [([],tm)] []; |
|
323 |
end; |
|
324 |
||
325 |
(* ------------------------------------------------------------------------- *) |
|
326 |
(* Special support for terms with an explicit function application operator. *) |
|
327 |
(* ------------------------------------------------------------------------- *) |
|
328 |
||
329 |
val appName = Name.fromString "."; |
|
330 |
||
331 |
fun mkFnApp (fTm,aTm) = (appName, [fTm,aTm]); |
|
332 |
||
333 |
fun mkApp f_a = Fn (mkFnApp f_a); |
|
334 |
||
335 |
fun destFnApp ((f,a) : Name.name * term list) = |
|
336 |
if not (Name.equal f appName) then raise Error "Term.destFnApp" |
|
337 |
else |
|
338 |
case a of |
|
339 |
[fTm,aTm] => (fTm,aTm) |
|
340 |
| _ => raise Error "Term.destFnApp"; |
|
341 |
||
342 |
val isFnApp = can destFnApp; |
|
343 |
||
344 |
fun destApp tm = |
|
345 |
case tm of |
|
346 |
Var _ => raise Error "Term.destApp" |
|
347 |
| Fn func => destFnApp func; |
|
348 |
||
349 |
val isApp = can destApp; |
|
350 |
||
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
351 |
fun listMkApp (f,l) = List.foldl mkApp f l; |
39348 | 352 |
|
353 |
local |
|
354 |
fun strip tms tm = |
|
355 |
case total destApp tm of |
|
356 |
SOME (f,a) => strip (a :: tms) f |
|
357 |
| NONE => (tm,tms); |
|
358 |
in |
|
359 |
fun stripApp tm = strip [] tm; |
|
360 |
end; |
|
361 |
||
362 |
(* ------------------------------------------------------------------------- *) |
|
363 |
(* Parsing and pretty printing. *) |
|
364 |
(* ------------------------------------------------------------------------- *) |
|
365 |
||
366 |
(* Operators parsed and printed infix *) |
|
367 |
||
368 |
val infixes = |
|
369 |
(ref o Print.Infixes) |
|
370 |
[(* ML symbols *) |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
371 |
{token = "/", precedence = 7, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
372 |
{token = "div", precedence = 7, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
373 |
{token = "mod", precedence = 7, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
374 |
{token = "*", precedence = 7, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
375 |
{token = "+", precedence = 6, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
376 |
{token = "-", precedence = 6, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
377 |
{token = "^", precedence = 6, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
378 |
{token = "@", precedence = 5, assoc = Print.RightAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
379 |
{token = "::", precedence = 5, assoc = Print.RightAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
380 |
{token = "=", precedence = 4, assoc = Print.NonAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
381 |
{token = "<>", precedence = 4, assoc = Print.NonAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
382 |
{token = "<=", precedence = 4, assoc = Print.NonAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
383 |
{token = "<", precedence = 4, assoc = Print.NonAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
384 |
{token = ">=", precedence = 4, assoc = Print.NonAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
385 |
{token = ">", precedence = 4, assoc = Print.NonAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
386 |
{token = "o", precedence = 3, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
387 |
{token = "->", precedence = 2, assoc = Print.RightAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
388 |
{token = ":", precedence = 1, assoc = Print.NonAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
389 |
{token = ",", precedence = 0, assoc = Print.RightAssoc}, |
39348 | 390 |
|
391 |
(* Logical connectives *) |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
392 |
{token = "/\\", precedence = ~1, assoc = Print.RightAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
393 |
{token = "\\/", precedence = ~2, assoc = Print.RightAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
394 |
{token = "==>", precedence = ~3, assoc = Print.RightAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
395 |
{token = "<=>", precedence = ~4, assoc = Print.RightAssoc}, |
39348 | 396 |
|
397 |
(* Other symbols *) |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
398 |
{token = ".", precedence = 9, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
399 |
{token = "**", precedence = 8, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
400 |
{token = "++", precedence = 6, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
401 |
{token = "--", precedence = 6, assoc = Print.LeftAssoc}, |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
402 |
{token = "==", precedence = 4, assoc = Print.NonAssoc}]; |
39348 | 403 |
|
404 |
(* The negation symbol *) |
|
405 |
||
406 |
val negation : string ref = ref "~"; |
|
407 |
||
408 |
(* Binder symbols *) |
|
409 |
||
410 |
val binders : string list ref = ref ["\\","!","?","?!"]; |
|
411 |
||
412 |
(* Bracket symbols *) |
|
413 |
||
414 |
val brackets : (string * string) list ref = ref [("[","]"),("{","}")]; |
|
415 |
||
416 |
(* Pretty printing *) |
|
417 |
||
418 |
fun pp inputTerm = |
|
419 |
let |
|
420 |
val quants = !binders |
|
421 |
and iOps = !infixes |
|
422 |
and neg = !negation |
|
423 |
and bracks = !brackets |
|
424 |
||
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
425 |
val bMap = |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
426 |
let |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
427 |
fun f (b1,b2) = (b1 ^ b2, b1, b2) |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
428 |
in |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
429 |
List.map f bracks |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
430 |
end |
39348 | 431 |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
432 |
val bTokens = op@ (unzip bracks) |
39348 | 433 |
|
434 |
val iTokens = Print.tokensInfixes iOps |
|
435 |
||
436 |
fun destI tm = |
|
437 |
case tm of |
|
438 |
Fn (f,[a,b]) => |
|
439 |
let |
|
440 |
val f = Name.toString f |
|
441 |
in |
|
442 |
if StringSet.member f iTokens then SOME (f,a,b) else NONE |
|
443 |
end |
|
444 |
| _ => NONE |
|
445 |
||
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
446 |
fun isI tm = Option.isSome (destI tm) |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
447 |
|
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
448 |
fun iToken (_,tok) = |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
449 |
Print.program |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
450 |
[(if tok = "," then Print.skip else Print.ppString " "), |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
451 |
Print.ppString tok, |
45778 | 452 |
Print.break]; |
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
453 |
|
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
454 |
val iPrinter = Print.ppInfixes iOps destI iToken |
39348 | 455 |
|
456 |
val specialTokens = |
|
457 |
StringSet.addList iTokens (neg :: quants @ ["$","(",")"] @ bTokens) |
|
458 |
||
459 |
fun vName bv s = StringSet.member s bv |
|
460 |
||
461 |
fun checkVarName bv n = |
|
462 |
let |
|
463 |
val s = Name.toString n |
|
464 |
in |
|
465 |
if vName bv s then s else "$" ^ s |
|
466 |
end |
|
467 |
||
468 |
fun varName bv = Print.ppMap (checkVarName bv) Print.ppString |
|
469 |
||
470 |
fun checkFunctionName bv n = |
|
471 |
let |
|
472 |
val s = Name.toString n |
|
473 |
in |
|
474 |
if StringSet.member s specialTokens orelse vName bv s then |
|
475 |
"(" ^ s ^ ")" |
|
476 |
else |
|
477 |
s |
|
478 |
end |
|
479 |
||
480 |
fun functionName bv = Print.ppMap (checkFunctionName bv) Print.ppString |
|
481 |
||
482 |
fun stripNeg tm = |
|
483 |
case tm of |
|
484 |
Fn (f,[a]) => |
|
485 |
if Name.toString f <> neg then (0,tm) |
|
486 |
else let val (n,tm) = stripNeg a in (n + 1, tm) end |
|
487 |
| _ => (0,tm) |
|
488 |
||
489 |
val destQuant = |
|
490 |
let |
|
491 |
fun dest q (Fn (q', [Var v, body])) = |
|
492 |
if Name.toString q' <> q then NONE |
|
493 |
else |
|
494 |
(case dest q body of |
|
495 |
NONE => SOME (q,v,[],body) |
|
496 |
| SOME (_,v',vs,body) => SOME (q, v, v' :: vs, body)) |
|
497 |
| dest _ _ = NONE |
|
498 |
in |
|
499 |
fn tm => Useful.first (fn q => dest q tm) quants |
|
500 |
end |
|
501 |
||
502 |
fun isQuant tm = Option.isSome (destQuant tm) |
|
503 |
||
504 |
fun destBrack (Fn (b,[tm])) = |
|
505 |
let |
|
506 |
val s = Name.toString b |
|
507 |
in |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
508 |
case List.find (fn (n,_,_) => n = s) bMap of |
39348 | 509 |
NONE => NONE |
510 |
| SOME (_,b1,b2) => SOME (b1,tm,b2) |
|
511 |
end |
|
512 |
| destBrack _ = NONE |
|
513 |
||
514 |
fun isBrack tm = Option.isSome (destBrack tm) |
|
515 |
||
516 |
fun functionArgument bv tm = |
|
517 |
Print.sequence |
|
45778 | 518 |
Print.break |
39348 | 519 |
(if isBrack tm then customBracket bv tm |
520 |
else if isVar tm orelse isConst tm then basic bv tm |
|
521 |
else bracket bv tm) |
|
522 |
||
523 |
and basic bv (Var v) = varName bv v |
|
524 |
| basic bv (Fn (f,args)) = |
|
45778 | 525 |
Print.inconsistentBlock 2 |
42102 | 526 |
(functionName bv f :: List.map (functionArgument bv) args) |
39348 | 527 |
|
528 |
and customBracket bv tm = |
|
529 |
case destBrack tm of |
|
530 |
SOME (b1,tm,b2) => Print.ppBracket b1 b2 (term bv) tm |
|
531 |
| NONE => basic bv tm |
|
532 |
||
533 |
and innerQuant bv tm = |
|
534 |
case destQuant tm of |
|
535 |
NONE => term bv tm |
|
536 |
| SOME (q,v,vs,tm) => |
|
537 |
let |
|
42102 | 538 |
val bv = StringSet.addList bv (List.map Name.toString (v :: vs)) |
39348 | 539 |
in |
540 |
Print.program |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
541 |
[Print.ppString q, |
39348 | 542 |
varName bv v, |
543 |
Print.program |
|
45778 | 544 |
(List.map (Print.sequence Print.break o varName bv) vs), |
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
545 |
Print.ppString ".", |
45778 | 546 |
Print.break, |
39348 | 547 |
innerQuant bv tm] |
548 |
end |
|
549 |
||
550 |
and quantifier bv tm = |
|
551 |
if not (isQuant tm) then customBracket bv tm |
|
45778 | 552 |
else Print.inconsistentBlock 2 [innerQuant bv tm] |
39348 | 553 |
|
554 |
and molecule bv (tm,r) = |
|
555 |
let |
|
556 |
val (n,tm) = stripNeg tm |
|
557 |
in |
|
45778 | 558 |
Print.inconsistentBlock n |
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
559 |
[Print.duplicate n (Print.ppString neg), |
39348 | 560 |
if isI tm orelse (r andalso isQuant tm) then bracket bv tm |
561 |
else quantifier bv tm] |
|
562 |
end |
|
563 |
||
564 |
and term bv tm = iPrinter (molecule bv) (tm,false) |
|
565 |
||
566 |
and bracket bv tm = Print.ppBracket "(" ")" (term bv) tm |
|
567 |
in |
|
568 |
term StringSet.empty |
|
569 |
end inputTerm; |
|
570 |
||
571 |
val toString = Print.toString pp; |
|
572 |
||
573 |
(* Parsing *) |
|
574 |
||
575 |
local |
|
576 |
open Parse; |
|
577 |
||
578 |
infixr 9 >>++ |
|
579 |
infixr 8 ++ |
|
580 |
infixr 7 >> |
|
581 |
infixr 6 || |
|
582 |
||
583 |
val isAlphaNum = |
|
584 |
let |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
585 |
val alphaNumChars = String.explode "_'" |
39348 | 586 |
in |
587 |
fn c => mem c alphaNumChars orelse Char.isAlphaNum c |
|
588 |
end; |
|
589 |
||
590 |
local |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
591 |
val alphaNumToken = atLeastOne (some isAlphaNum) >> String.implode; |
39348 | 592 |
|
593 |
val symbolToken = |
|
594 |
let |
|
595 |
fun isNeg c = str c = !negation |
|
596 |
||
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
597 |
val symbolChars = String.explode "<>=-*+/\\?@|!$%&#^:;~" |
39348 | 598 |
|
599 |
fun isSymbol c = mem c symbolChars |
|
600 |
||
601 |
fun isNonNegSymbol c = not (isNeg c) andalso isSymbol c |
|
602 |
in |
|
603 |
some isNeg >> str || |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
604 |
(some isNonNegSymbol ++ many (some isSymbol)) >> |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
605 |
(String.implode o op::) |
39348 | 606 |
end; |
607 |
||
608 |
val punctToken = |
|
609 |
let |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
610 |
val punctChars = String.explode "()[]{}.," |
39348 | 611 |
|
612 |
fun isPunct c = mem c punctChars |
|
613 |
in |
|
614 |
some isPunct >> str |
|
615 |
end; |
|
616 |
||
617 |
val lexToken = alphaNumToken || symbolToken || punctToken; |
|
618 |
||
619 |
val space = many (some Char.isSpace); |
|
620 |
in |
|
621 |
val lexer = (space ++ lexToken ++ space) >> (fn (_,(tok,_)) => tok); |
|
622 |
end; |
|
623 |
||
624 |
fun termParser inputStream = |
|
625 |
let |
|
626 |
val quants = !binders |
|
627 |
and iOps = !infixes |
|
628 |
and neg = !negation |
|
629 |
and bracks = ("(",")") :: !brackets |
|
630 |
||
42102 | 631 |
val bracks = List.map (fn (b1,b2) => (b1 ^ b2, b1, b2)) bracks |
39348 | 632 |
|
42102 | 633 |
val bTokens = List.map #2 bracks @ List.map #3 bracks |
39348 | 634 |
|
635 |
fun possibleVarName "" = false |
|
636 |
| possibleVarName s = isAlphaNum (String.sub (s,0)) |
|
637 |
||
638 |
fun vName bv s = StringSet.member s bv |
|
639 |
||
640 |
val iTokens = Print.tokensInfixes iOps |
|
641 |
||
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
642 |
fun iMk (f,a,b) = Fn (Name.fromString f, [a,b]) |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
643 |
|
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
644 |
val iParser = parseInfixes iOps iMk any |
39348 | 645 |
|
646 |
val specialTokens = |
|
647 |
StringSet.addList iTokens (neg :: quants @ ["$"] @ bTokens) |
|
648 |
||
649 |
fun varName bv = |
|
650 |
some (vName bv) || |
|
651 |
(some (Useful.equal "$") ++ some possibleVarName) >> snd |
|
652 |
||
653 |
fun fName bv s = |
|
654 |
not (StringSet.member s specialTokens) andalso not (vName bv s) |
|
655 |
||
656 |
fun functionName bv = |
|
657 |
some (fName bv) || |
|
658 |
(some (Useful.equal "(") ++ any ++ some (Useful.equal ")")) >> |
|
659 |
(fn (_,(s,_)) => s) |
|
660 |
||
661 |
fun basic bv tokens = |
|
662 |
let |
|
663 |
val var = varName bv >> (Var o Name.fromString) |
|
664 |
||
665 |
val const = |
|
666 |
functionName bv >> (fn f => Fn (Name.fromString f, [])) |
|
667 |
||
668 |
fun bracket (ab,a,b) = |
|
669 |
(some (Useful.equal a) ++ term bv ++ some (Useful.equal b)) >> |
|
670 |
(fn (_,(tm,_)) => |
|
671 |
if ab = "()" then tm else Fn (Name.fromString ab, [tm])) |
|
672 |
||
673 |
fun quantifier q = |
|
674 |
let |
|
675 |
fun bind (v,t) = |
|
676 |
Fn (Name.fromString q, [Var (Name.fromString v), t]) |
|
677 |
in |
|
678 |
(some (Useful.equal q) ++ |
|
679 |
atLeastOne (some possibleVarName) ++ |
|
680 |
some (Useful.equal ".")) >>++ |
|
681 |
(fn (_,(vs,_)) => |
|
682 |
term (StringSet.addList bv vs) >> |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
683 |
(fn body => List.foldr bind body vs)) |
39348 | 684 |
end |
685 |
in |
|
686 |
var || |
|
687 |
const || |
|
42102 | 688 |
first (List.map bracket bracks) || |
689 |
first (List.map quantifier quants) |
|
39348 | 690 |
end tokens |
691 |
||
692 |
and molecule bv tokens = |
|
693 |
let |
|
694 |
val negations = many (some (Useful.equal neg)) >> length |
|
695 |
||
696 |
val function = |
|
697 |
(functionName bv ++ many (basic bv)) >> |
|
698 |
(fn (f,args) => Fn (Name.fromString f, args)) || |
|
699 |
basic bv |
|
700 |
in |
|
701 |
(negations ++ function) >> |
|
702 |
(fn (n,tm) => funpow n (fn t => Fn (Name.fromString neg, [t])) tm) |
|
703 |
end tokens |
|
704 |
||
705 |
and term bv tokens = iParser (molecule bv) tokens |
|
706 |
in |
|
707 |
term StringSet.empty |
|
708 |
end inputStream; |
|
709 |
in |
|
710 |
fun fromString input = |
|
711 |
let |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
712 |
val chars = Stream.fromList (String.explode input) |
39348 | 713 |
|
714 |
val tokens = everything (lexer >> singleton) chars |
|
715 |
||
716 |
val terms = everything (termParser >> singleton) tokens |
|
717 |
in |
|
718 |
case Stream.toList terms of |
|
719 |
[tm] => tm |
|
720 |
| _ => raise Error "Term.fromString" |
|
721 |
end; |
|
722 |
end; |
|
723 |
||
724 |
local |
|
39443
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
725 |
val antiquotedTermToString = |
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents:
39353
diff
changeset
|
726 |
Print.toString (Print.ppBracket "(" ")" pp); |
39348 | 727 |
in |
728 |
val parse = Parse.parseQuotation antiquotedTermToString fromString; |
|
729 |
end; |
|
730 |
||
731 |
end |
|
732 |
||
733 |
structure TermOrdered = |
|
734 |
struct type t = Term.term val compare = Term.compare end |
|
735 |
||
736 |
structure TermMap = KeyMap (TermOrdered); |
|
737 |
||
738 |
structure TermSet = ElementSet (TermMap); |