Scheme Compiler の勉強 (11) - fixnum, char

1.3 Unary Primitives の fixnum->char までテストが通るようになった。

  • 一旦基盤ができてしまえば、テストを追加=>primitive を追加=>テストを実行、とループを回せる。結局テキスト通りでちゃんとうまくいく。
;; gauche 用に変更した箇所。

(define *is-prim* '())
(define *arg-count* '())
(define *emitter* '())

(define-syntax define-primitive 
  (syntax-rules () 
    [(_ (prim-name arg* ...) b b* ...) 
     (begin 
       (set! *is-prim* (acons 'prim-name #t *is-prim*))
       (set! *arg-count* (acons 'prim-name (length '(arg* ...)) *is-prim*))
       (set! *emitter* (acons 'prim-name 
			      (lambda (arg* ...) b b* ...) *emitter*)))]))
;; LLVM 用に変更した箇所

(define (emit-function-header)
  (emit "define i32 @scheme_entry() nounwind {")
  (emit "entry:")
  (emit "    %ret = alloca i32"))

(define (emit-function-footer)
  (emit "    %retval = load i32* %ret")
  (emit "    ret i32 %retval")
  (emit "}"))
(define (emit-expr expr)
  (cond
   [(immediate? expr) (emit-immediate expr)]
   [(primcall? expr) (emit-primcall expr)]
   [else (error) ]))

;; LLVM 用に変更した箇所
(define (emit-immediate expr)
  (emit "    store i32 ~s, i32* %ret" (immediate-rep expr)))
;; ユニークな変数名を作成する簡易手続き

(define unique-var
  (let ((count 0))
    (lambda ()
      (set! count (+ 1 count))
      (format #f "%var~a" count))))

;; define-primitive での定義; 多分無駄なことをやっている

(define-primitive ($fxadd1 expr)
  (let* ((%val (unique-var))
	 (%tmp (unique-var)))
    (emit-expr expr)
    (emit "    ~a = load i32* %ret" %val)
    (emit "    ~a = add i32 ~s, ~a" %tmp (immediate-rep 1) %val)
    (emit "    store i32 ~a, i32* %ret" %tmp)))