1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; Standard Library Procedures and Macros ;;
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 ;; define (procedural syntax)
9 (define-macro (define args . body)
11 `(define ,(car args) (lambda ,(cdr args) ,@body))
16 (define-macro (begin . sequence)
17 `((lambda () ,@sequence)))
21 (define-macro (caar l) `(car (car ,l)))
22 (define-macro (cadr l) `(car (cdr ,l)))
23 (define-macro (cdar l) `(cdr (car ,l)))
24 (define-macro (cddr l) `(cdr (cdr ,l)))
25 (define-macro (caaar l) `(car (car (car ,l))))
26 (define-macro (caadr l) `(car (car (cdr ,l))))
27 (define-macro (cadar l) `(car (cdr (car ,l))))
28 (define-macro (caddr l) `(car (cdr (cdr ,l))))
29 (define-macro (cdaar l) `(cdr (car (car ,l))))
30 (define-macro (cdadr l) `(cdr (car (cdr ,l))))
31 (define-macro (cddar l) `(cdr (cdr (car ,l))))
32 (define-macro (cdddr l) `(cdr (cdr (cdr ,l))))
33 (define-macro (cadddr l) `(car (cdr (cdr (cdr ,l)))))
36 ;; Methods used in remaining macro definitions:
41 (cons (proc (car l)) (map proc (cdr l)))))
45 (define-macro (let args . body)
46 `((lambda ,(map (lambda (x) (car x)) args)
47 ,@body) ,@(map (lambda (x) (cadr x)) args)))
51 (define-macro (let* args . body)
55 (let* ,(cdr args) ,@body))))
59 (define-macro (while condition . body)
60 (let ((loop (gensym)))
64 (begin ,@body (,loop))))
70 (define (cond-predicate clause) (car clause))
71 (define (cond-actions clause) (cdr clause))
72 (define (cond-else-clause? clause)
73 (eq? (cond-predicate clause) 'else))
75 (define (expand-clauses clauses)
78 (let ((first (car clauses))
80 (if (cond-else-clause? first)
82 `(begin ,@(cond-actions first))
83 (error "else clause isn't last in cond expression."))
84 `(if ,(cond-predicate first)
85 (begin ,@(cond-actions first))
86 ,(expand-clauses rest))))))
88 (define-macro (cond . clauses)
90 (error "cond requires at least one clause.")
91 (expand-clauses clauses)))))
96 (define (expand-and-expressions expressions)
97 (let ((first (car expressions))
98 (rest (cdr expressions)))
102 ,(expand-and-expressions rest)
105 (define-macro (and . expressions)
106 (if (null? expressions)
108 (expand-and-expressions expressions)))
114 (define (expand-or-expressions expressions)
115 (if (null? expressions)
117 (let ((first (car expressions))
118 (rest (cdr expressions))
120 `(let ((,val ,first))
123 ,(expand-or-expressions rest))))))
125 (define-macro (or . expressions)
126 (expand-or-expressions expressions))
131 (define-macro (not x)
134 ;; FUNCTIONAL PROGRAMMING
136 (define (fold-left proc init l)
139 (fold-left proc (proc init (car l)) (cdr l))))
141 (define (reduce-left proc init l)
146 (fold-left proc (proc (car l) (car (cdr l))) (cdr (cdr l))))))
151 ; Rational primitives
153 (define (numerator x)
158 (define (denominator x)
166 (make-rational (fix:+ (fix:* (numerator x) (denominator y))
167 (fix:* (denominator x) (numerator y)))
168 (fix:* (denominator x) (denominator y))))
171 (make-rational (fix:- (fix:* (numerator x) (denominator y))
172 (fix:* (denominator x) (numerator y)))
173 (fix:* (denominator x) (denominator y))))
176 (make-rational (fix:* (numerator x) (numerator y))
177 (fix:* (denominator x) (denominator y))))
180 (make-rational (fix:* (numerator x) (denominator y))
181 (fix:* (denominator x) (numerator y))))
184 (make-rational (denominator x) (numerator x)))
186 ; Type dispatch and promotion
188 (define (type-dispatch ops x)
193 (define (promote-dispatch ops x y)
197 ((cdr ops) x (fixnum->flonum y)))
199 ((cdr ops) (fixnum->flonum x) y)
205 (type-dispatch (cons fix:neg flo:neg) x))
208 (type-dispatch (cons fix:abs flo:abs) x))
210 (define (flo:1+ x) (flo:+ x 1.0))
211 (define (flo:1- x) (flo:- x 1.0))
214 (type-dispatch (cons fix:1+ flo:1+) n))
217 (type-dispatch (cons fix:1- flo:1-) n))
219 (define (apply-to-flonum op x)
220 (if (flonum? x) (op x) x))
223 (apply-to-flonum flo:round x))
225 (apply-to-flonum flo:floor x))
227 (apply-to-flonum flo:ceiling x))
229 (apply-to-flonum flo:truncate x))
233 (define (fix:/ x y) ; Non-standard definition while we don't have rationals
234 (if (fix:= 0 (fix:remainder x y))
236 (flo:/ (fixnum->flonum x) (fixnum->flonum y))))
238 (define (pair+ x y) (promote-dispatch (cons fix:+ flo:+) x y))
239 (define (pair- x y) (promote-dispatch (cons fix:- flo:-) x y))
240 (define (pair* x y) (promote-dispatch (cons fix:* flo:*) x y))
241 (define (pair/ x y) (promote-dispatch (cons fix:/ flo:/) x y))
243 (define (pair> x y) (promote-dispatch (cons fix:> flo:>) x y))
244 (define (pair< x y) (promote-dispatch (cons fix:< flo:<) x y))
245 (define (pair>= x y) (promote-dispatch (cons fix:>= flo:>=) x y))
246 (define (pair<= x y) (promote-dispatch (cons fix:<= flo:<=) x y))
247 (define (pair= x y) (promote-dispatch (cons fix:= flo:=) x y))
253 (fold-left pair+ 0 args))
255 (define (- first . rest)
258 (pair- first (apply + rest))))
261 (fold-left pair* 1 args))
263 (define (/ first . rest)
266 (pair/ first (apply * rest))))
268 (define (quotient n1 n2)
269 (fix:quotient n1 n2))
271 (define (remainder n1 n2)
272 (fix:remainder n1 n2))
274 (define modulo remainder)
278 (define (test-relation rel l)
283 (if (rel (car l) (car (cdr l)))
284 (test-relation rel (cdr l))
288 (test-relation pair= args))
291 (test-relation pair> args))
294 (test-relation pair< args))
297 (test-relation pair>= args))
300 (test-relation pair<= args))
304 (define (zero? x) (pair= x 0.0))
305 (define (positive x) (pair> x 0.0))
306 (define (odd? n) (pair= (remainder n 2) 0))
307 (define (odd? n) (not (pair= (remainder n 2) 0)))
310 ; Current state of the numerical tower
311 (define (complex? x) #f)
312 (define (real? x) #t)
313 (define (rational? x) #t)
314 (define (integer? x) (= x (round x)))
315 (define (exact? x) (fixnum? x))
316 (define (inexact? x) (flonum? x))
320 (if (ratnum? x) #t #f))))
326 (define (list . args) args)
328 ; Return number of items in list
330 (define (iter a count)
333 (iter (cdr a) (fix:+ count 1))))
336 ; Join two lists together
340 (cons (car l1) (join (cdr l1) l2))))
342 ; Append an arbitrary number of lists together
343 (define (append . lists)
346 (if (null? (cdr lists))
348 (join (car lists) (apply append (cdr lists))))))
350 ; Reverse the contents of a list
354 (append (reverse (cdr l)) (list (car l)))))
359 ; Test for the while macro.
363 (display counter) (newline)
364 (set! counter (- counter 1))))
366 ; Basic iterative summation. Run this on large numbers to
367 ; test garbage collection and tail-call optimization.
370 (define (sum-iter total count maxcount)
371 (if (fix:> count maxcount)
373 (sum-iter (fix:+ total count) (fix:+ count 1) maxcount)))
377 ; Recursive summation. Use this to compare with tail call
378 ; optimized iterative algorithm.
379 (define (sum-recurse n)
382 (fix:+ n (sum-recurse (fix:- n 1)))))
390 "This program is free software; you can redistribute it and/or modify
391 it under the terms of the GNU General Public License as published by
392 the Free Software Foundation; either version 3 of the License, or
393 (at your option) any later version.
395 This program is distributed in the hope that it will be useful,
396 but WITHOUT ANY WARRANTY; without even the implied warranty of
397 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
398 GNU General Public License for more details.
400 You should have received a copy of the GNU General Public License
401 along with this program. If not, see http://www.gnu.org/licenses/.
406 "Welcome to scheme.forth.jl!
408 Copyright (C) 2016 Tim Vaughan.
409 This program comes with ABSOLUTELY NO WARRANTY; for details type '(license)'.