142 lines
3.1 KiB
Plaintext
142 lines
3.1 KiB
Plaintext
; Syntax and shorthands
|
|
|
|
(define = eq?)
|
|
(define not null?)
|
|
|
|
(define caar (lambda (lst) (car (car lst))))
|
|
(define cdar (lambda (lst) (cdr (car lst))))
|
|
(define caddr (lambda (lst) (car (cddr lst))))
|
|
(define cadddr (lambda (lst) (cadr (cddr lst))))
|
|
|
|
; I/O
|
|
|
|
(define print
|
|
(lambda (object)
|
|
(write object)
|
|
(newline)))
|
|
|
|
; The least dispensable list operations
|
|
|
|
(define equal?
|
|
(lambda (x1 x2)
|
|
(if (eq? x1 x2)
|
|
t
|
|
(if (pair? x1)
|
|
(if (pair? x2)
|
|
(if (equal? (car x1) (car x2))
|
|
(equal? (cdr x1) (cdr x2))))))))
|
|
|
|
(define length
|
|
(lambda (lst)
|
|
((lambda (n)
|
|
(while lst
|
|
(set! n (+ n 1))
|
|
(set! lst (cdr lst)))
|
|
n)
|
|
0)))
|
|
|
|
(define append
|
|
(lambda (L1 L2)
|
|
(if (null? L1)
|
|
L2
|
|
(cons (car L1)
|
|
(append (cdr L1) L2)))))
|
|
|
|
(define map
|
|
(lambda (proc lst)
|
|
((lambda (result)
|
|
(while lst
|
|
(set! result (cons (proc (car lst)) result))
|
|
(set! lst (cdr lst)))
|
|
(reverse! result))
|
|
'())))
|
|
|
|
(define for-each
|
|
(lambda (proc lst)
|
|
(while lst
|
|
(proc (car lst))
|
|
(set! lst (cdr lst)))))
|
|
|
|
; Macros
|
|
|
|
(define macroexpand
|
|
(lambda (exp)
|
|
(if (atom? exp)
|
|
exp
|
|
(if (get (car exp) 'special-form)
|
|
((get (car exp) 'special-form) exp)
|
|
(if (get (car exp) 'macro)
|
|
(macroexpand ((get (car exp) 'macro) (cdr exp)))
|
|
(map macroexpand exp))))))
|
|
|
|
(put 'quote 'special-form
|
|
(lambda (exp) exp))
|
|
|
|
(put 'lambda 'special-form
|
|
(lambda (exp)
|
|
(cons 'lambda
|
|
(cons (cadr exp)
|
|
(map macroexpand (cddr exp))))))
|
|
|
|
; Other special forms don't need special treatment, but you might want
|
|
; to add syntax-checking.
|
|
|
|
(define define-macro
|
|
(lambda (keyword expander)
|
|
(put keyword 'macro expander)))
|
|
|
|
(define-macro 'and
|
|
(lambda (args)
|
|
(if (null? args)
|
|
t
|
|
(if (null? (cdr args))
|
|
(car args)
|
|
(list 'if (car args) (cons 'and (cdr args)))))))
|
|
|
|
(define-macro 'or
|
|
(lambda (args)
|
|
(if (null? args)
|
|
nil
|
|
(if (null? (cdr args))
|
|
(car args)
|
|
(list
|
|
((lambda (test-var)
|
|
(list 'lambda (list test-var)
|
|
(list 'if test-var test-var (cons 'or (cdr args)))))
|
|
(gensym))
|
|
(car args))))))
|
|
|
|
(define-macro 'let
|
|
(lambda (args)
|
|
(cons
|
|
(cons 'lambda (cons (map car (car args)) (cdr args)))
|
|
(map cadr (car args)))))
|
|
|
|
(define make-begin
|
|
(lambda (lst)
|
|
(if (null? (cdr lst))
|
|
(car lst)
|
|
(cons 'begin lst))))
|
|
|
|
(define-macro 'cond
|
|
(lambda (clauses)
|
|
(if (null? clauses)
|
|
nil
|
|
(if (eq? (caar clauses) 'else)
|
|
(make-begin (cdar clauses))
|
|
(list 'if
|
|
(caar clauses)
|
|
(make-begin (cdar clauses))
|
|
(cons 'cond (cdr clauses)))))))
|
|
|
|
; This procedure replaces the system default read-eval-print loop:
|
|
|
|
(define top-level-driver
|
|
(lambda ()
|
|
(write '>)
|
|
((lambda (exp)
|
|
(if (eq? the-eof-object exp)
|
|
(set! top-level-driver nil)
|
|
(print (eval (macroexpand exp)))))
|
|
(read))))
|