list.scm 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey
  3. ; write s-expressions
  4. ; Memory
  5. (define *memory*)
  6. (define *hp*)
  7. (define (initialize-memory! size)
  8. (set! *memory* (allocate-memory size))
  9. ;(if (null-pointer? *memory*)
  10. ; (error "out of memory, unable to continue"))
  11. (set! *hp* *memory*))
  12. (define (allocate size)
  13. (let ((p *hp*))
  14. (set! *hp* (address+ *hp* size))
  15. p))
  16. (define (words->a-units x)
  17. (* x 4))
  18. ; Data
  19. (define tag-bits 1)
  20. (define tag-mask (- (shift-left 1 tag-bits) 1))
  21. (define tag/fixnum 0)
  22. (define tag/pair 1)
  23. (define (enter-fixnum x)
  24. (+ (shift-left x tag-bits) tag/fixnum))
  25. (define (extract-fixnum x)
  26. (arithmetic-shift-right x tag-bits))
  27. (define (make-predicate tag)
  28. (lambda (x)
  29. (= tag (bitwise-and x tag-mask))))
  30. (define fixnum? (make-predicate tag/fixnum))
  31. (define my-pair? (make-predicate tag/pair))
  32. (define (make-accessor tag offset)
  33. (lambda (x)
  34. (word-ref (address+ (integer->address (+ x (- 0 tag)))
  35. (words->a-units offset)))))
  36. (define (make-setter tag offset)
  37. (lambda (x v)
  38. (word-set! (address+ (integer->address (+ x (- 0 tag)))
  39. (words->a-units offset))
  40. v)))
  41. (define pair-size 16) ; bytes
  42. (define head (make-accessor tag/pair 0))
  43. (define tail (make-accessor tag/pair 1))
  44. (define set-head! (make-setter tag/pair 0))
  45. (define set-tail! (make-setter tag/pair 1))
  46. (define (make-pair x y)
  47. (let ((p (+ tag/pair (address->integer (allocate pair-size)))))
  48. (set-head! p x)
  49. (set-tail! p y)
  50. p))
  51. (define null tag/pair)
  52. (define (my-null? x)
  53. (= x null))
  54. (define (print-s-exp x out)
  55. (cond ((fixnum? x)
  56. (write-number-no-newline (extract-fixnum x) out))
  57. ((my-null? x)
  58. (write-char #\( out)
  59. (write-char #\) out))
  60. ((my-pair? x)
  61. (write-char #\( out)
  62. (print-s-exp (head x) out)
  63. (let loop ((x (tail x)))
  64. (cond ((my-null? x)
  65. (write-char #\) out))
  66. ((my-pair? x)
  67. (write-char #\space out)
  68. (print-s-exp (head x) out)
  69. (loop (tail x)))
  70. (else
  71. (write-char #\space out)
  72. (write-char #\. out)
  73. (write-char #\space out)
  74. (print-s-exp x out)
  75. (write-char #\) out)))))))
  76. (define *input-port*)
  77. (define *peeked-char?* #f)
  78. (define *peeked-char*)
  79. (define (readc)
  80. (cond (*peeked-char?*
  81. (set! *peeked-char?* #f)
  82. *peeked-char*)
  83. (else
  84. (call-with-values
  85. (lambda ()
  86. (read-char *input-port*))
  87. (lambda (ch eof? status)
  88. (if eof? (ascii->char 0) ch))))))
  89. (define (peekc)
  90. (if *peeked-char?*
  91. *peeked-char*
  92. (call-with-values
  93. (lambda ()
  94. (read-char *input-port*))
  95. (lambda (ch eof? status)
  96. (if eof?
  97. (ascii->char 0)
  98. (begin
  99. (set! *peeked-char?* #t)
  100. (set! *peeked-char* ch)
  101. ch))))))
  102. (define (digit? ch)
  103. (let ((ch (char->ascii ch)))
  104. (and (>= ch (char->ascii #\0))
  105. (<= ch (char->ascii #\9)))))
  106. (define (read-number)
  107. (let loop ()
  108. (case (peekc)
  109. ((#\-)
  110. (readc)
  111. (- 0 (really-read-number)))
  112. ((#\+)
  113. (readc)
  114. (really-read-number))
  115. (else
  116. (really-read-number)))))
  117. (define (really-read-number)
  118. (let loop ((r 0))
  119. (let ((ch (peekc)))
  120. (cond ((digit? ch)
  121. (readc)
  122. (loop (+ (- (char->ascii ch) (char->ascii #\0))
  123. (* r 10))))
  124. (else r)))))
  125. (define (read-s-exp)
  126. (case (peekc)
  127. ((#\space #\newline)
  128. (readc)
  129. (read-s-exp))
  130. ((#\- #\+)
  131. (enter-fixnum (read-number)))
  132. ((#\()
  133. (readc)
  134. (read-list))
  135. (else
  136. (if (digit? (peekc))
  137. (enter-fixnum (read-number))
  138. -1))))
  139. (define (read-list)
  140. (case (peekc)
  141. ((#\space #\newline)
  142. (readc)
  143. (read-list))
  144. ((#\))
  145. (readc)
  146. null)
  147. ((#\.)
  148. (readc) ; eat the dot
  149. (let ((res (read-s-exp)))
  150. (if (read-r-paren)
  151. res
  152. -1)))
  153. (else
  154. (let ((head (read-s-exp)))
  155. (make-pair head (read-list))))))
  156. (define (read-r-paren)
  157. (case (peekc)
  158. ((#\space #\newline)
  159. (readc)
  160. (read-r-paren))
  161. ((#\))
  162. #t)
  163. (else #f)))
  164. ; Printing integers
  165. ; Return 10**n such that 10**n <= x < 10**(n+1)
  166. (define (integer-mask x)
  167. (do ((x x (quotient x 10))
  168. (mask 1 (* mask 10)))
  169. ((< x 10) mask)))
  170. ; Write positive integer X out to PORT
  171. (define (write-number x port)
  172. (write-number-no-newline x port)
  173. (write-char '#\newline port))
  174. (define (write-number-no-newline x port)
  175. (let ((x (cond ((< x 0)
  176. (write-char '#\- port)
  177. (- 0 x))
  178. (else
  179. x))))
  180. (let loop ((x x) (mask (integer-mask x)))
  181. (let ((digit (quotient x mask)))
  182. (write-char (ascii->char (+ digit (char->ascii '#\0))) port)
  183. (if (> mask 1)
  184. (loop (remainder x mask) (quotient mask 10)))))))
  185. (define (test size)
  186. (initialize-memory! size)
  187. (let ((s-exp (make-pair (enter-fixnum 1)
  188. (make-pair (enter-fixnum 2)
  189. (make-pair (make-pair (enter-fixnum 3) (enter-fixnum 4))
  190. null))))
  191. (out (current-output-port)))
  192. (print-s-exp s-exp out)
  193. (newline out)
  194. (set! *input-port* (current-input-port))
  195. (print-s-exp (read-s-exp) out)
  196. (newline out)))