
(define (caar x) (car (car x)))
(define (cadr x) (car (cdr x)))
(define (cdar x) (car (cdr x)))
(define (cddr x) (cdr (cdr x)))

(define (caaar x) (car (car (car x))))
(define (cdddr x) (cdr (cdr (cdr x))))

(define (caaaar x) (car (car (car (car x)))))
(define (cddddr x) (cdr (cdr (cdr (cdr x)))))

(define (caddr x) (car (cdr (cdr x))))
(define (cadddr x) (car (cdr (cdr (cdr x)))))

(define (caadr x) (car (car (cdr x))))
(define (caaddr x) (car (car (cdr (cdr x)))))

(define (call-with-input-file str proc) 
  (let ((port (llopen_input_file str)))
    (proc port) 
    (close-port port)))

(define (or a b)  ;; NOT special forms!
  (if a #t b))

(define (and a b) ;; NOT special forms!
  (if a b nil))

(define (call-with-output-file str proc) 
  (let ((port (llopen_output_file str)))
    (proc port) 
    (close-port port)))

(define system !)

(define (popen command type)
  (cond ((eq? type 'r) (!read command))
	((eq? type 'w) (!write command)) 
	(print "Invalid type")))

(define (list-ref lst n)
  (cond ((not lst) nil)
	((> n 0)
	 (list-ref (cdr lst) (- n 1)))
	(else
	 (car lst))))

(define (nth n lst)  (list-ref lst n))

(define (map proc lst)
  (if (null? lst) nil
      (let ((a (proc (car lst))))
	(cons a
	      (map proc (cdr lst))))))

(define nl "
")

(define (append l l2)
  (if l
      (cons (car l) (append (cdr l) l2))
      l2))

(define (equal? obj1 obj2)
  (cond ((symbol? obj1) (if (symbol? obj2) (eq? obj1 obj2)))
	((number? obj1) (if (number? obj2) (= obj1 obj2)))
	((pair? obj1) (if (pair? obj2) 
			  (if (equal? (car obj1) (car obj2))
			      (equal? (cdr obj1) (cdr obj2)))))
	(else (eq? obj1 obj2))))
			       

(define (filter	proc lst)
  (cond ((null? lst) nil)
	((proc (car lst)) (cons (car lst) (filter proc (cdr lst))))
	(else 
	 (filter proc (cdr lst)))))
			  

;; Library package loading library 
 
(define *LIBRARY-PACKAGE-LIST* nil)

(define (add-library name thunk)
  (set! *LIBRARY-PACKAGE-LIST* 
	(cons (list name thunk)
	      *LIBRARY-PACKAGE-LIST*)))

(define (load-library which)
  (map (lambda (entry)
	 ((cadr entry)))
       (filter (lambda (entry)
		 (equal? (car entry) which))
	       *LIBRARY-PACKAGE-LIST*))
  t)

(add-library 'whoopie (lambda () (load whoopie-config-file)))
