This file is indexed.

/usr/share/hol88-2.02.19940316/Library/trs/struct.ml is in hol88-library-source 2.02.19940316-35.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
% struct.ml                                             (c) R.J.Boulton 1990 %
%----------------------------------------------------------------------------%


% Function to merge two association lists, failing if the lists are %
% inconsistent.                                                     %

% The first element of the pair at the head of l2 is looked-up in l1. If the %
% second element of the pair obtained is equal to the second element of the  %
% pair at the head of l2, then the head of l2 is discarded. Otherwise, the   %
% merge fails. If the look-up in l1 fails, the head of l2 is retained.       %

letrec merge l1 l2 =

   % : ((* # **) list -> (* # **) list -> (* # **) list) %

   if (null l2)
   then l1
   else ((let p = assoc (fst (hd l2)) l1
          in  if (snd p = snd (hd l2))
              then (merge l1 (tl l2))
              else failwith `merge`)

        ??[`assoc`] (hd l2).(merge l1 (tl l2))

        );;


% Function to merge two `match' lists. %

let join (avtl,attl) ((bvtl,bttl) : (term # term) list # (type # type) list) =

   % : ((term # term) list # (type # type) list ->   %
   %    (term # term) list # (type # type) list ->   %
   %    (term # term) list # (type # type) list    ) %

   (merge avtl bvtl,merge attl bttl) ??[`merge`] failwith `no match`;;


% Function to remove a bound-variable from a `match' list. %

% Any pairs in the variable-term association list which have the %
% bound-variable as their first element are filtered out.        %

let remove_bv bv ((vtl,ttl) : (term # term) list # (type # type) list) =

   % : (term -> (term # term) list # (type # type) list ->    %
   %                 (term # term) list # (type # type) list) %

   (filter (\x.not ((fst x) = bv)) vtl,ttl);;


% Function for matching two types. %

% The first type given, p, must be the more general.                         %

% If p is a simple polymorphic type (i.e. one containing no constructors)    %
% then it can match any type. A single item association list is constructed  %
% from the two types in such a case.                                         %

% If p is not a simple type, it is split up into a constructor and a list of %
% simpler types. An attempt is made to split t, also. If this fails, then no %
% match can be made. If the constructors obtained from p and t are different %
% then the match must fail. The lists of simpler types obtained from         %
% decomposing p and t are converted to a list of pairs, the match failing if %
% the original lists were not of the same length. The function is then       %
% applied recursively to each pair of the new list, and the results are      %
% merged. If merging fails, the whole match fails.                           %

letrec match_type p t =

   % : (type -> type -> (type # type) list) %

   if (is_vartype p)
   then [(p,t)]
   else let (pc,ptypl) = dest_type p
        and (tc,ttypl) = ((dest_type t) ? failwith `no match`)
        in  if (pc = tc)
            then ((itlist merge (map (\(x,y).match_type x y)
                                        (combine (ptypl,ttypl))) [])
                 ??[`merge`;`combine`] failwith `no match`
                 )
            else failwith `no match`;;


% Function for matching two terms. %

% The first term given, p, must be the more general.                        %

% The function consists of four cases.                                      %

% p is a constant. If t is not a constant, the match fails. If the names of %
% p and t are different, the match fails. Constants cannot be wildcards, so %
% only the types need adding to the `match' list. One might think the match %
% should fail if the types are different, but this is not the case.         %
% Consider the `=' function, for instance. The types must match, however.   %

% p is a variable. A variable can match any term, provided its type can be  %
% matched to that of the term.                                              %

% p is an abstraction. An abstraction can only match another abstraction.   %
% p and t are decomposed into their bound-variables and bodies. The bound-  %
% variables are matched to obtain the type matchings. The bodies are also   %
% matched. The resultant matchings are then merged, and the bound-variable  %
% is then removed from the variable-term list to allow for renaming of      %
% bound-variables. Note that the merge has to be done before the bound-var. %
% is removed to ensure the bound-variables correspond in the body.          %

% p is a combination. A combination can only match another combination.     %
% p and t are decomposed into their rators and rands. The two rators are    %
% matched against each other. The two rands are matched. Then the resulting %
% `match' lists are merged.                                                 %

letrec match_term p t =

   % : (term -> term -> (term # term) list # (type # type) list) %

   if (is_const p) then if (is_const t)
                        then if (fst (dest_const p) = fst (dest_const t))
                             then ([],match_type (type_of p) (type_of t))
                             else failwith `no match`
                        else failwith `no match`
   if (is_var p) then ([(p,t)],match_type (type_of p) (type_of t))
   if (is_abs p) then
     (let (pbv,pbody) = dest_abs p
      and (tbv,tbody) = ((dest_abs t) ? failwith `no match`)
      in  remove_bv pbv (join (match_term pbv tbv) (match_term pbody tbody)))
   if (is_comb p) then
     (let (prator,prand) = dest_comb p
      and (trator,trand) = ((dest_comb t) ? failwith `no match`)
      in  join (match_term prator trator) (match_term prand trand))
   else fail;;


% Function to match a term pattern inside a term %

% The function applies match_term to the pattern and the term. If this fails %
% the function is called recursively on any possible sub-terms of the term.  %
% If all these attempts to match fail, the whole evaluation fails.           %

letrec match_internal_term p t =

   % : (term -> term -> (term # term) list # (type # type) list) %

   match_term p t
   ??[`no match`]             (match_internal_term p (rator t))
   ??[`no match`;`dest_comb`] (match_internal_term p (rand t))
   ??[`no match`;`dest_comb`] (match_internal_term p (snd (dest_abs t)))
   ??[`no match`;`dest_abs`]  failwith `no match`;;


%----------------------------------------------------------------------------%


% Abstract datatype for wildcard variables to be used in pattern matching %

abstype wildvar = term

   % Function to convert a wildvar into a term %

   with show_wildvar w = rep_wildvar w

       % : (wildvar -> term) %

   % Function to make a wildvar from a term. The term must be a variable %

   and  make_wildvar t =

       % : (term -> wildvar) %

       if (is_var t)
       then (abs_wildvar t)
       else failwith `make_wildvar -- term is not a variable`;;


% Function to make a list of wildvars out of a list of terms %

let wildvarlist varl = map make_wildvar varl;;

   % : (term list -> wildvar list) %


%----------------------------------------------------------------------------%


% Abstract datatype for wildcard types to be used in pattern matching %

abstype wildtype = type

   % Function to convert a wildtype into a type %

   with show_wildtype w = rep_wildtype w

       % : (wildtype -> type) %

   % Function to make a wildtype from a type.         %
   % The type must be a `primitive' polymorphic type. %

   and  make_wildtype t =

       % : (type -> wildtype) %

       if (is_vartype t)
       then (abs_wildtype t)
       else failwith `make_wildtype -- type is not polymorphic`;;


% Function to make a list of wildtypes out of a list of types %

let wildtypelist typl = map make_wildtype typl;;

   % : (type list -> wildtype list) %


%----------------------------------------------------------------------------%


% Abstract datatype for patterns used to match terms %

abstype termpattern = term # wildvar list # wildtype list

   % Function to convert a termpattern to its representing type %

   with show_termpattern p = rep_termpattern p

       % : (termpattern -> (term # wildvar list # wildtype list)) %

   % Function to make a termpattern from a term, a list of wildcard variables %
   % and a list of wildcard types.                                            %

   and  make_termpattern (tm,wvl,wtl) =

       % : ((term # wildvar list # wildtype list) -> termpattern) %

       % Convert wildcard variables to their representing variables %

       let varl = map show_wildvar wvl

       % Convert wildcard types to their representing type %

       and typl = map show_wildtype wtl

       % Form a termpattern if and only if the lists of wildcard variables %
       % and wildcard types are sets (i.e. contain no repetitions) and all %
       % the wildcard variables specified are free variables in tm and all %
       % the wildcard types specified are `primitive' polymorphic types    %
       % occurring in tm.                                                  %

       in  if (no_rep varl) then
              if (no_rep typl) then
                 if (is_subset (get_freevars tm) varl) then
                    if (is_subset (get_primvartypes tm) typl) then

                       (abs_termpattern (tm,wvl,wtl))

                    else failwith `make_termpattern -- wildtype not in term`
                 else failwith `make_termpattern -- wildvar not in term`
              else failwith `make_termpattern -- duplicate wildtype`
           else failwith `make_termpattern -- duplicate wildvar`;;


% Function to convert a termpattern into its representing type, and the %
% wildvars and wildtypes within that to their representing types.       %
% So, function makes all of a termpattern visible.                      %

let show_full_termpattern p =

   % : (termpattern -> (term # term list # type list)) %

   let (tm,wvl,wtl) = show_termpattern p
   in  (tm,(map show_wildvar wvl),(map show_wildtype wtl));;


% Function to make a termpattern from a term, a list of terms, and a list of %
% types. The term represents the pattern. The list of terms represents the   %
% variables which are to be taken as wildcards, and the list of types        %
% represents the `primitive' polymorphic types which are to be taken as      %
% wildcards.                                                                 %

let make_full_termpattern (tm,terml,typel) =

   % : ((term # term list # type list) -> termpattern) %

   make_termpattern (tm,wildvarlist terml,wildtypelist typel);;


% Function to make a termpattern out of a term by using the free variables in %
% the term as wildvars and the `primitive' polymorphic types as wildtypes.    %

let autotermpattern t =

   % : (term -> termpattern) %

   make_full_termpattern (t,get_freevars t,get_primvartypes t);;


%----------------------------------------------------------------------------%


% Abstract datatype for the result of matching a termpattern against a term %

abstype matching = ((wildvar # term) list # (wildtype # type) list)

   % Function to convert a matching to its representing type %

   with show_matching m = rep_matching m

       % : (matching -> ((wildvar # term) list # (wildtype # type) list)) %

   % A matching with no bindings %

   and  null_matching = abs_matching ([],[])

       % : (matching) %

   % Function to form a matching from a termpattern and a term %

   and  make_matching p t =

       % : (termpattern -> term -> matching) %

           % Extract low-level components of termpattern %

           let (tm,varl,typl) = show_full_termpattern p

               % Use `match_term' to attempt a matching of the template tm  %
               % against the term t. If this fails, `make_matching' fails.  %
               % If it succeeds the (term # term) list # (type # type) list %
               % returned by `match_term' is bound to the pair (vpl,tpl)    %
               % for further analysis/processing.                           %

           in  let (vpl,tpl) = match_term tm t

               % The (term # term) list component returned by `match_term'   %
               % is a list of pairs such that the first element of the pair  %
               % is a variable in tm, and the second element of the pair is  %
               % the term in t that the variable has been matched to.        %

               % Bound-variables in tm do not appear in the result of        %
               % `match_term'. Some of the variables which do appear may not %
               % have been specified as wildvars. The match must fail if     %
               % such a variable does not (when its type has been            %
               % instantiated) match itself in the list returned by          %
               % `match_term'. The (type # type) list, returned by           %
               % `match_term' is used to perform the instantiation.          %

               % Types are dealt with similarly, except that there is no     %
               % equivalent action to instantiation.                         %

               % The matching we are trying to construct should look like    %
               % the result of `match_term' except that the variables and    %
               % types from tm should be converted to wildcards, and only    %
               % those of them that appear as wildcards in the termpattern   %
               % should be included.                                         %

               % Now we know what we are trying to achieve, let us define    %
               % some functions to help us.                                  %

               % f is used to convert the term or type which is representing %
               % a wildcard into the appropriate wildcard type.              %

               and f w (a,b) = ((w a),b)

                  % : ((* -> **) -> (* # ***) -> (** # ***)) %

               % `instant_type' instantiates the type of a variable using a  %
               % (type # type) list in which the first element of each pair  %
               % is a `primitive' type. The embedded function `change_type'  %
               % does the real work. `instant_type' splits the variable into %
               % its name and type, applies `change_type' to the type, and   %
               % then reconstructs the variable using the new type.          %

               and instant_type ttl v =

                  % : ((type # type) list -> term -> term) %

                  % `change_type' instantiates a type. If the type is        %
                  % `primitive', it is looked-up in the instantiation list.  %
                  % If found, the corresponding instance is returned. If not %
                  % the type itself is returned. If the type is              %
                  % not `primitive', it is decomposed into a constructor and %
                  % a list of simpler types. Each of the latter are then     %
                  % instantiated, and the type is reconstructed.             %

                 (letrec change_type ttl typ =

                     % : ((type # type) list -> type -> type) %

                     if (is_primtype typ)
                     then ((snd (assoc typ ttl)) ? typ)
                     else (let (s,l) = dest_type typ
                           in  mk_type (s,(map (change_type ttl) l)))
                  in (let (s,t) = dest_var v
                      in  mk_var (s,(change_type ttl t)))
                 )

                   % `build' filters xxl removing any pairs whose first  %
                   % element is not in xl. If lf applied to the first    %
                   % element of such a pair is not equal to the second   %
                   % element of the pair, then the match being performed %
                   % is failed.                                          %

                   % `build' is used to build a matching from a `match'  %
                   % list and a wildcard list. Any variable or type in   %
                   % the `match' list but not in the wildcard list must  %
                   % match itself (allowing for type instantiation -     %
                   % hence the need for lf), and will not be included in %
                   % the result.                                         %

               in (letrec build lf xl xxl =

                      % : ((* -> **) -> * list -> (* # **) list ->          %
                      %                                      (* # **) list) %

                      if (null xxl)
                      then []
                      else if (mem ((fst o hd) xxl) xl)
                           then (hd xxl).(build lf xl (tl xxl))
                           else if ((lf o fst o hd) xxl = (snd o hd) xxl)
                                then (build lf xl (tl xxl))
                                else failwith `no match`

                   % Note : assumes all variables which could be wildvars   %
                   %        appear in the matching returned by `match_term' %

                   in abs_matching (
                        (map (f make_wildvar)
                                (build (instant_type tpl) varl vpl)),
                        (map (f make_wildtype) (build (\x.x) typl tpl)))
                  )

   % Function to combine two (consistent) matchings into a single matching %

   % Split the two matchings into wildvar and wildtype `match' lists. Merge %
   % the two resulting wildvar lists and the two resulting wildtype lists.  %
   % If either merge fails, the match fails.                                %

   and  join_matchings m n =

       % : (matching -> matching -> matching) %

           let mwvl,mwtl = rep_matching m
           and nwvl,nwtl = rep_matching n
           in  abs_matching ((merge mwvl nwvl),(merge mwtl nwtl))
                  ?? [`merge`] failwith `no match`;;


% Function to convert a matching into its representing type, and the %
% wildvars and wildtypes within that to their representing types.    %
% So, function makes all of a matching visible.                      %

let show_full_matching m =

   % : (matching -> ((term # term) list # (type # type) list)) %

       let wvl,wtl = show_matching m
       and f (w,t) = ((show_wildvar w),t)
       and g (w,t) = ((show_wildtype w),t)
       in  ((map f wvl),(map g wtl));;


% Function to lookup a wildvar in a matching, and return the term to %
% which it is bound.                                                 %

let match_of_var m wv =

   % : (matching -> wildvar -> term) %

   (snd o (assoc wv) o fst o show_matching) m
   ?? [`assoc`]
      failwith `match_of_var -- unknown wildvar (variable)`;;


% Function to lookup a wildtype in a matching, and return the type to %
% which it is bound.                                                  %

let match_of_type m wt =

   % : (matching -> wildtype -> type) %

   (snd o (assoc wt) o snd o show_matching) m
   ?? [`assoc`]
      failwith `match_of_type -- unknown wildtype (polymorphic type)`;;


%----------------------------------------------------------------------------%


% Datatype for lazy evaluation of alternate matchings %

% Nomatch means there is no way to match.                                    %
% Match means there is at least one way to match, and specifies the matching %
% (which may be null). The second element of the pair is a function to       %
% generate any other matchings if they exist.                                %

rectype result_of_match = Nomatch
                        | Match of matching # (void -> result_of_match);;


% Abbreviation for a result_of_match which is a match with no bindings %

let Match_null = Match(null_matching,(\().Nomatch));;


% Function to append two lazy lists (`result_of_matches') %

% `approms' appends two `result_of_matches' which are essentially just lazy %
% lists of matchings. The result must be kept as lazy as possible. This     %
% function is also used to OR two `result_of_matches', since this operation %
% corresponds exactly to appending them.                                    %

% The arguments to `approms' are actually functions from void to a          %
% `result_of_match', so that as little evaluation as necessary is done.     %

% The function is defined in an analogous way to `append' on lists.         %

letrec approms rom1fn rom2fn () =

   % : ((void -> result_of_match) -> (void -> result_of_match) ->           %
   %                                             (void -> result_of_match)) %

   case (rom1fn ())
   of (Nomatch) . (rom2fn ())
    | (Match (m,romfn)) . (Match (m,approms romfn rom2fn));;


% Function to convert a Boolean value to a result_of_match %

let bool_to_rom b =

   % : (bool -> result_of_match) %

   if b
   then Match_null
   else Nomatch;;


% Function to convert a result_of_match to a Boolean value %

% Note that information may be thrown away in this process. %

let rom_to_bool r =

   % : (result_of_match -> bool) %

   not (r = Nomatch);;


% Abbreviation for the datatype representing side-conditions %

% When applied to a matching, a side-condition performs tests on the        %
% bindings in the matching, and returns a `lazy list' of any successful new %
% bindings.                                                                 %

lettype side_condition = matching -> result_of_match;;


%----------------------------------------------------------------------------%