Dylan mode
AخA
1
Module: locators-internals Synopsis: Abstract modeling of locations Author: Andy Armstrong Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: See License.txt in this distribution for details.
2
Warranty: Distributed WITHOUT WARRANTY OF ANY KIND define open generic locator-server (locator ::
3
<locator>) => (server :: false-or(
4
<server-locator>)); define open generic locator-host (locator ::
5
<locator>) => (host :: false-or(
6
<string>)); define open generic locator-volume (locator ::
7
<locator>) => (volume :: false-or(
8
<string>)); define open generic locator-directory (locator ::
9
<locator>) => (directory :: false-or(
10
<directory-locator>)); define open generic locator-relative? (locator ::
11
<locator>) => (relative? ::
12
<boolean>); define open generic locator-path (locator ::
13
<locator>) => (path ::
14
<sequence>); define open generic locator-base (locator ::
15
<locator>) => (base :: false-or(
16
<string>)); define open generic locator-extension (locator ::
17
<locator>) => (extension :: false-or(
18
<string>)); /// Locator classes define open abstract class
19
<directory-locator> (
20
<physical-locator>) end class
21
<directory-locator>; define open abstract class
22
<file-locator> (
23
<physical-locator>) end class
24
<file-locator>; define method as (class ==
25
<directory-locator>, string ::
26
<string>) => (locator ::
27
<directory-locator>) as(
28
<native-directory-locator>, string) end method as; define method make (class ==
29
<directory-locator>, #key server :: false-or(
30
<server-locator>) = #f, path ::
31
<sequence> = #[], relative? ::
32
<boolean> = #f, name :: false-or(
33
<string>) = #f) => (locator ::
34
<directory-locator>) make(
35
<native-directory-locator>, server: server, path: path, relative?: relative?, name: name) end method make; define method as (class ==
36
<file-locator>, string ::
37
<string>) => (locator ::
38
<file-locator>) as(
39
<native-file-locator>, string) end method as; define method make (class ==
40
<file-locator>, #key directory :: false-or(
41
<directory-locator>) = #f, base :: false-or(
42
<string>) = #f, extension :: false-or(
43
<string>) = #f, name :: false-or(
44
<string>) = #f) => (locator ::
45
<file-locator>) make(
46
<native-file-locator>, directory: directory, base: base, extension: extension, name: name)
47
end method make; /// Locator coercion //---*** andrewa: This caching
48
scheme doesn't work yet, so disable it. define constant $cache-locators?
49
= #f; define constant $cache-locator-strings? = #f; define constant
50
$locator-to-string-cache = make(
51
<object-table>, weak: #"key"); define constant $string-to-locator-cache = make(
52
<string-table>, weak: #"value"); define open generic locator-as-string (class
53
:: subclass(
54
<string>), locator ::
55
<locator>) => (string ::
56
<string>); define open generic string-as-locator (class
57
:: subclass(
58
<locator>), string ::
59
<string>) => (locator ::
60
<locator>); define sealed sideways method as
61
(class :: subclass(
62
<string>), locator ::
63
<locator>) => (string ::
64
<string>) let string = element($locator-to-string-cache,
65
locator, default: #f);
66
if (string) as(class,
67
string) else let string
68
= locator-as-string(class,
69
locator); if ($cache-locator-strings?)
70
element($locator-to-string-cache,
71
locator) := string;
72
else string end end
73
end method as; define
74
sealed sideways method
75
as (class :: subclass(
76
<locator>), string ::
77
<string>) => (locator ::
78
<locator>) let locator
79
= element($string-to-locator-cache,
80
string,
81
default:
82
#f); if
83
(instance?(locator,
84
class))
85
locator
86
else let
87
locator
88
= string-as-locator(class,
89
string);
90
if ($cache-locators?)
91
element($string-to-locator-cache,
92
string)
93
:= locator;
94
else locator
95
end end
96
end method
97
as; ///
98
Locator
99
conditions
100
define
101
class
102
<locator-error>
103
(
104
<format-string-condition>,
105
<error>)
106
end
107
class
108
<locator-error>;
109
define
110
function
111
locator-error
112
(format-string
113
::
114
<string>,
115
#rest
116
format-arguments)
117
error(make(
118
<locator-error>,
119
format-string:
120
format-string,
121
format-arguments:
122
format-arguments))
123
end
124
function
125
locator-error;
126
///
127
Useful
128
locator
129
protocols
130
define
131
open
132
generic
133
locator-test
134
(locator
135
::
136
<directory-locator>)
137
=>
138
(test
139
::
140
<function>);
141
define
142
method
143
locator-test
144
(locator
145
::
146
<directory-locator>)
147
=>
148
(test
149
::
150
<function>)
151
\=
152
end
153
method
154
locator-test;
155
define
156
open
157
generic
158
locator-might-have-links?
159
(locator
160
::
161
<directory-locator>)
162
=>
163
(links?
164
::
165
<boolean>);
166
define
167
method
168
locator-might-have-links?
169
(locator
170
::
171
<directory-locator>)
172
=>
173
(links?
174
::
175
singleton(#f))
176
#f
177
end
178
method
179
locator-might-have-links?;
180
define
181
method
182
locator-relative?
183
(locator
184
::
185
<file-locator>)
186
=>
187
(relative?
188
::
189
<boolean>)
190
let
191
directory
192
=
193
locator.locator-directory;
194
~directory
195
|
196
directory.locator-relative?
197
end
198
method
199
locator-relative?;
200
define
201
method
202
current-directory-locator?
203
(locator
204
::
205
<directory-locator>)
206
=>
207
(current-directory?
208
::
209
<boolean>)
210
locator.locator-relative?
211
&
212
locator.locator-path
213
=
214
#[#"self"]
215
end
216
method
217
current-directory-locator?;
218
define
219
method
220
locator-directory
221
(locator
222
::
223
<directory-locator>)
224
=>
225
(parent
226
::
227
false-or(
228
<directory-locator>))
229
let
230
path
231
=
232
locator.locator-path;
233
unless
234
(empty?(path))
235
make(object-class(locator),
236
server:
237
locator.locator-server,
238
path:
239
copy-sequence(path,
240
end:
241
path.size
242
-
243
1),
244
relative?:
245
locator.locator-relative?)
246
end
247
end
248
method
249
locator-directory;
250
///
251
Simplify
252
locator
253
define
254
open
255
generic
256
simplify-locator
257
(locator
258
::
259
<physical-locator>)
260
=>
261
(simplified-locator
262
::
263
<physical-locator>);
264
define
265
method
266
simplify-locator
267
(locator
268
::
269
<directory-locator>)
270
=>
271
(simplified-locator
272
::
273
<directory-locator>)
274
let
275
path
276
=
277
locator.locator-path;
278
let
279
relative?
280
=
281
locator.locator-relative?;
282
let
283
resolve-parent?
284
=
285
~locator.locator-might-have-links?;
286
let
287
simplified-path
288
=
289
simplify-path(path,
290
resolve-parent?:
291
resolve-parent?,
292
relative?:
293
relative?);
294
if
295
(path
296
~=
297
simplified-path)
298
make(object-class(locator),
299
server:
300
locator.locator-server,
301
path:
302
simplified-path,
303
relative?:
304
locator.locator-relative?)
305
else
306
locator
307
end
308
end
309
method
310
simplify-locator;
311
define
312
method
313
simplify-locator
314
(locator
315
::
316
<file-locator>)
317
=>
318
(simplified-locator
319
::
320
<file-locator>)
321
let
322
directory
323
=
324
locator.locator-directory;
325
let
326
simplified-directory
327
=
328
directory
329
&
330
simplify-locator(directory);
331
if
332
(directory
333
~=
334
simplified-directory)
335
make(object-class(locator),
336
directory:
337
simplified-directory,
338
base:
339
locator.locator-base,
340
extension:
341
locator.locator-extension)
342
else
343
locator
344
end
345
end
346
method
347
simplify-locator;
348
///
349
Subdirectory
350
locator
351
define
352
open
353
generic
354
subdirectory-locator
355
(locator
356
::
357
<directory-locator>,
358
#rest
359
sub-path)
360
=>
361
(subdirectory
362
::
363
<directory-locator>);
364
define
365
method
366
subdirectory-locator
367
(locator
368
::
369
<directory-locator>,
370
#rest
371
sub-path)
372
=>
373
(subdirectory
374
::
375
<directory-locator>)
376
let
377
old-path
378
=
379
locator.locator-path;
380
let
381
new-path
382
=
383
concatenate-as(
384
<simple-object-vector>,
385
old-path,
386
sub-path);
387
make(object-class(locator),
388
server:
389
locator.locator-server,
390
path:
391
new-path,
392
relative?:
393
locator.locator-relative?)
394
end
395
method
396
subdirectory-locator;
397
///
398
Relative
399
locator
400
define
401
open
402
generic
403
relative-locator
404
(locator
405
::
406
<physical-locator>,
407
from-locator
408
::
409
<physical-locator>)
410
=>
411
(relative-locator
412
::
413
<physical-locator>);
414
define
415
method
416
relative-locator
417
(locator
418
::
419
<directory-locator>,
420
from-locator
421
::
422
<directory-locator>)
423
=>
424
(relative-locator
425
::
426
<directory-locator>)
427
let
428
path
429
=
430
locator.locator-path;
431
let
432
from-path
433
=
434
from-locator.locator-path;
435
case
436
~locator.locator-relative?
437
&
438
from-locator.locator-relative?
439
=>
440
locator-error
441
("Cannot
442
find
443
relative
444
path
445
of
446
absolute
447
locator
448
%=
449
from
450
relative
451
locator
452
%=",
453
locator,
454
from-locator);
455
locator.locator-server
456
~=
457
from-locator.locator-server
458
=>
459
locator;
460
path
461
=
462
from-path
463
=>
464
make(object-class(locator),
465
path:
466
vector(#"self"),
467
relative?:
468
#t);
469
otherwise
470
=>
471
make(object-class(locator),
472
path:
473
relative-path(path,
474
from-path,
475
test:
476
locator.locator-test),
477
relative?:
478
#t);
479
end
480
end
481
method
482
relative-locator;
483
define
484
method
485
relative-locator
486
(locator
487
::
488
<file-locator>,
489
from-directory
490
::
491
<directory-locator>)
492
=>
493
(relative-locator
494
::
495
<file-locator>)
496
let
497
directory
498
=
499
locator.locator-directory;
500
let
501
relative-directory
502
=
503
directory
504
&
505
relative-locator(directory,
506
from-directory);
507
if
508
(relative-directory
509
~=
510
directory)
511
simplify-locator
512
(make(object-class(locator),
513
directory:
514
relative-directory,
515
base:
516
locator.locator-base,
517
extension:
518
locator.locator-extension))
519
else
520
locator
521
end
522
end
523
method
524
relative-locator;
525
define
526
method
527
relative-locator
528
(locator
529
::
530
<physical-locator>,
531
from-locator
532
::
533
<file-locator>)
534
=>
535
(relative-locator
536
::
537
<physical-locator>)
538
let
539
from-directory
540
=
541
from-locator.locator-directory;
542
case
543
from-directory
544
=>
545
relative-locator(locator,
546
from-directory);
547
~locator.locator-relative?
548
=>
549
locator-error
550
("Cannot
551
find
552
relative
553
path
554
of
555
absolute
556
locator
557
%=
558
from
559
relative
560
locator
561
%=",
562
locator,
563
from-locator);
564
otherwise
565
=>
566
locator;
567
end
568
end
569
method
570
relative-locator;
571
///
572
Merge
573
locators
574
define
575
open
576
generic
577
merge-locators
578
(locator
579
::
580
<physical-locator>,
581
from-locator
582
::
583
<physical-locator>)
584
=>
585
(merged-locator
586
::
587
<physical-locator>);
588
///
589
Merge
590
locators
591
define
592
method
593
merge-locators
594
(locator
595
::
596
<directory-locator>,
597
from-locator
598
::
599
<directory-locator>)
600
=>
601
(merged-locator
602
::
603
<directory-locator>)
604
if
605
(locator.locator-relative?)
606
let
607
path
608
=
609
concatenate(from-locator.locator-path,
610
locator.locator-path);
611
simplify-locator
612
(make(object-class(locator),
613
server:
614
from-locator.locator-server,
615
path:
616
path,
617
relative?:
618
from-locator.locator-relative?))
619
else
620
locator
621
end
622
end
623
method
624
merge-locators;
625
define
626
method
627
merge-locators
628
(locator
629
::
630
<file-locator>,
631
from-locator
632
::
633
<directory-locator>)
634
=>
635
(merged-locator
636
::
637
<file-locator>)
638
let
639
directory
640
=
641
locator.locator-directory;
642
let
643
merged-directory
644
=
645
if
646
(directory)
647
merge-locators(directory,
648
from-locator)
649
else
650
simplify-locator(from-locator)
651
end;
652
if
653
(merged-directory
654
~=
655
directory)
656
make(object-class(locator),
657
directory:
658
merged-directory,
659
base:
660
locator.locator-base,
661
extension:
662
locator.locator-extension)
663
else
664
locator
665
end
666
end
667
method
668
merge-locators;
669
define
670
method
671
merge-locators
672
(locator
673
::
674
<physical-locator>,
675
from-locator
676
::
677
<file-locator>)
678
=>
679
(merged-locator
680
::
681
<physical-locator>)
682
let
683
from-directory
684
=
685
from-locator.locator-directory;
686
if
687
(from-directory)
688
merge-locators(locator,
689
from-directory)
690
else
691
locator
692
end
693
end
694
method
695
merge-locators;
696
///
697
Locator
698
protocols
699
define
700
sideways
701
method
702
supports-open-locator?
703
(locator
704
::
705
<file-locator>)
706
=>
707
(openable?
708
::
709
<boolean>)
710
~locator.locator-relative?
711
end
712
method
713
supports-open-locator?;
714
define
715
sideways
716
method
717
open-locator
718
(locator
719
::
720
<file-locator>,
721
#rest
722
keywords,
723
#key,
724
#all-keys)
725
=>
726
(stream
727
::
728
<stream>)
729
apply(open-file-stream,
730
locator,
731
keywords)
732
end
733
method
734
open-locator;
735
MIME types defined: text/x-dylan
.