next up previous
Next: 5 Closureクラス Up: ソフトウェア特論 講義資料 JavaによるScheme言語処理系: Jscheme Previous: 3 Primitiveクラス

4 Scheme関数定義の登録.SchemePrimitives.java

SchemePrimitives.javaは,primitives.scmを 文字列として,SchemePrimitives.CODEに登録した SchemePrimitivesクラスを定義しています. primitives.scmは以下のようなファイルになっています.

;; Scheme primitives implemented in Scheme.
;; The quasiquote, and a few others, are
;; from Darius Bacon <djello@well.com>
;; (But then, he started with my PAIP code,
;;  and modified it.)
;; - Peter Norvig

;;;;; Extensions: new names for old procedures

(define call/cc    call-with-current-continuation)
(define first      car)
(define second     cadr)
(define third      caddr)
(define rest       cdr)
(define set-first! set-car!)
(define set-rest!  set-cdr!)

;;;;;;;;;;;;;;;; Standard Scheme Macros

(define or              
  (macro args 
    (if (null? args) 
        #f
        (cons 'cond (map list args)))))

(define and             
  (macro args 
    (cond ((null? args) #t)
          ((null? (rest args)) (first args))
          (else (list 'if (first args)
                  (cons 'and (rest args)) #f)))))

(define quasiquote 
  (macro (x) 
    (define (constant? exp)
      (if (pair? exp)
          (eq? (car exp) 'quote)
          (not (symbol? exp))))
    (define (combine-skeletons left right exp)
      (cond
       ((and (constant? left) (constant? right)) 
        (if (and (eqv? (eval left) (car exp))
                 (eqv? (eval right) (cdr exp)))
            (list 'quote exp)
            (list 'quote (cons (eval left)
                               (eval right)))))
       ((null? right) (list 'list left))
       ((and (pair? right) (eq? (car right) 'list))
        (cons 'list (cons left (cdr right))))
       (else (list 'cons left right))))
    (define (expand-quasiquote exp nesting)
      (cond
       ((vector? exp)
        (list 'apply 'vector
           (expand-quasiquote (vector->list exp)
                              nesting)))
       ((not (pair? exp)) 
        (if (constant? exp) exp (list 'quote exp)))
       ((and (eq? (car exp) 'unquote)
             (= (length exp) 2))
        (if (= nesting 0)
            (second exp)
            (combine-skeletons
                ''unquote 
                (expand-quasiquote (cdr exp)
                                   (- nesting 1))
                exp)))
       ((and (eq? (car exp) 'quasiquote)
             (= (length exp) 2))
        (combine-skeletons
             ''quasiquote 
             (expand-quasiquote (cdr exp)
                                (+ nesting 1))
             exp))
       ((and (pair? (car exp))
             (eq? (caar exp) 'unquote-splicing)
             (= (length (car exp)) 2))
        (if (= nesting 0)
            (list 'append (second (first exp))
                  (expand-quasiquote (cdr exp)
                                     nesting))
            (combine-skeletons
                (expand-quasiquote (car exp)
                                   (- nesting 1))
                (expand-quasiquote (cdr exp)
                                   nesting)
                exp)))
       (else (combine-skeletons
                (expand-quasiquote (car exp)
                                   nesting)
                (expand-quasiquote (cdr exp)
                                    nesting)
                exp))))
    (expand-quasiquote x 0)))

(define let 
  (macro (bindings . body) 
    (define (named-let name bindings body)
      `(let ((,name #f))
         (set! ,name (lambda
                        ,(map first bindings)
                        . ,body))
         (,name . ,(map second bindings))))
    (if (symbol? bindings) 
        (named-let bindings
                   (first body) (rest body))
        `((lambda ,(map first bindings)
                  . ,body)
            . ,(map second bindings)))))

(define let* 
  (macro (bindings . body)
    (if (null? bindings) `((lambda () . ,body))
        `(let (,(first bindings))
           (let* ,(rest bindings) . ,body)))))

(define letrec
  (macro (bindings . body)
    (let ((vars (map first bindings))
          (vals (map second bindings)))
    `(let ,(map (lambda (var) `(,var #f)) vars)
       ,@(map (lambda (var val)
                     `(set! ,var ,val)) vars vals)
       . ,body))))
    
(define case
  (macro (exp . cases)
    (define (do-case case)
      (cond ((not (pair? case))
             (error "bad syntax in case" case))
            ((eq? (first case) 'else) case)
            (else
               `((member __exp__ ',(first case))
                  . ,(rest case)))))
    `(let ((__exp__ ,exp))
          (cond . ,(map do-case cases)))))

(define do
  (macro (bindings test-and-result . body)
    (let ((variables (map first bindings))
          (inits (map second bindings))
          (steps (map (lambda (clause)
                        (if (null? (cddr clause))
                            (first clause)   
                            (third clause)))
                      bindings))
          (test (first test-and-result))
          (result (rest test-and-result)))
      `(letrec ((__loop__
                 (lambda ,variables
                   (if ,test
                       (begin . ,result)
                       (begin 
                         ,@body
                         (__loop__ . ,steps))))))
         (__loop__ . ,inits)))))

(define delay
  (macro (exp) 
    (define (make-promise proc)
      (let ((result-ready? #f)
            (result #f))
        (lambda ()
          (if result-ready?
              result
              (let ((x (proc)))
                (if result-ready?
                    result
                    (begin (set! result-ready? #t)
                           (set! result x)
                           result)))))))
    `(,make-promise (lambda () ,exp))))

;;;;;;;;;;;;;;;; Extensions

(define time 
  (macro (exp . rest)
         `(time-call (lambda () ,exp) . ,rest)))


generated through LaTeX2HTML. M.Inaba 平成18年5月6日