File: xport.scm

package info (click to toggle)
scsh 0.5.1-2
  • links: PTS
  • area: non-free
  • in suites: potato, slink
  • size: 6,540 kB
  • ctags: 8,656
  • sloc: lisp: 39,346; ansic: 13,466; sh: 1,669; makefile: 624
file content (170 lines) | stat: -rw-r--r-- 4,730 bytes parent folder | download
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
; Copyright (c) 1993, 1994 Richard Kelsey and Jonathan Rees.  See file COPYING.


; Extensible ports

; Input ports

(define-record-type extensible-input-port
  (local-data
   methods)
  ())

(define make-extensible-input-port extensible-input-port-maker)

(define-record-type input-port-methods
  (close-port
   read-char
   peek-char
   char-ready?
   current-column
   current-row
   )
  ())

(define make-input-port-methods input-port-methods-maker)

; Output ports

(define-record-type extensible-output-port
  (local-data
   methods)
  ())

(define make-extensible-output-port extensible-output-port-maker)

(define-record-type output-port-methods
  (close-port
   write-char
   write-string
   force-output
   fresh-line
   current-column
   current-row
   )
  ())

(define make-output-port-methods output-port-methods-maker)

; Operations

; CLOSE-PORT must work on both types of extensible ports.

(define-exception-handler (enum op close-port)
  (lambda (opcode args)
    (let ((port (car args)))
      (cond ((extensible-input-port? port)
	     ((input-port-methods-close-port
	       (extensible-input-port-methods port))
	      (extensible-input-port-local-data port)))
	    ((extensible-output-port? port)
	     ((output-port-methods-close-port
	       (extensible-output-port-methods port))
	      (extensible-output-port-local-data port)))
	    (else
	     (raise-port-exception opcode args))))))

(define (raise-port-exception opcode args)
  (signal-exception opcode args))

; Predicates
; These won't work as the VM does not raise an exception when predicates are
; applied to records.

;(define-exception-handler (enum op input-port?)
;  (lambda (opcode args)
;    (extensible-input-port? (car args))))

;(define-exception-handler (enum op output-port?)
;  (lambda (opcode args)
;    (extensible-output-port? (car args))))

; These will work for any code loaded subsequently...

(define (input-port? thing)
  (or ((structure-ref ports input-port?) thing)
      (extensible-input-port? thing)))

(define (output-port? thing)
  (or ((structure-ref ports output-port?) thing)
      (extensible-output-port? thing)))

; Other methods

(define (define-input-port-method op method)
  (define-exception-handler op
    (lambda (opcode args)
      (let ((port (car args)))
	(if (extensible-input-port? port)
	    ((method (extensible-input-port-methods port))
	     (extensible-input-port-local-data port))
	    (raise-port-exception opcode args))))))
  
(define-input-port-method (enum op read-char) input-port-methods-read-char)
(define-input-port-method (enum op peek-char) input-port-methods-peek-char)
(define-input-port-method (enum op char-ready?) input-port-methods-char-ready?)

(define (define-output-port-method op arg-count method)
  (define-exception-handler op
    (case arg-count
      ((0)
       (lambda (opcode args)
	 (let ((port (car args)))
	   (if (extensible-output-port? port)
	       ((method (extensible-output-port-methods port))
		(extensible-output-port-local-data port))
	       (raise-port-exception opcode args)))))
      ((1)
       (lambda (opcode args)
	 (let ((port (cadr args)))
	   (if (extensible-output-port? port)
	       ((method (extensible-output-port-methods port))
		(extensible-output-port-local-data port)
		(car args))
	       (raise-port-exception opcode args))))))))
  
(define-output-port-method (enum op write-char)
  1 output-port-methods-write-char)
(define-output-port-method (enum op write-string)
  1 output-port-methods-write-string)
(define-output-port-method (enum op force-output)
  0 output-port-methods-force-output)

(define (make-new-port-method id input-method output-method default)
  (lambda (port)
    (cond ((extensible-input-port? port)
	   ((input-method (extensible-input-port-methods port))
	    (extensible-input-port-local-data port)))
	  ((extensible-output-port? port)
	   ((output-method (extensible-output-port-methods port))
	    (extensible-output-port-local-data port)))
	  (else
	   (default port)))))

(define current-column
  (make-new-port-method 'current-column
			input-port-methods-current-column
			output-port-methods-current-column
			(lambda (port) #f)))

(define current-row
  (make-new-port-method 'current-row
			input-port-methods-current-row
			output-port-methods-current-row
			(lambda (port) #f)))

(define (make-new-output-port-method id method default)
  (lambda (port)
    (if (extensible-output-port? port)
	((method (extensible-output-port-methods port))
	 (extensible-output-port-local-data port))
	(default port))))

(define fresh-line
  (make-new-output-port-method 'fresh-line
			       output-port-methods-fresh-line
			       newline))
									 


(define force-output (structure-ref ports force-output))