ikarus/src/racompiler.ss

154 lines
4.3 KiB
Scheme
Raw Normal View History

#!/usr/bin/env ikarus --script
(define (racompile x)
;;;
(define-syntax record-case
(lambda (x)
(define (enumerate fld* i)
(syntax-case fld* ()
[() #'()]
[(x . x*)
(with-syntax ([i i] [i* (enumerate #'x* (fx+ i 1))])
#'(i . i*))]))
(define (generate-body ctxt cls*)
(syntax-case cls* (else)
[() (with-syntax ([x x]) #'(error #f "unmatched ~s in ~s" v #'x))]
[([else b b* ...]) #'(begin b b* ...)]
[([(rec-name rec-field* ...) b b* ...] . rest) (identifier? #'rec-name)
(with-syntax ([altern (generate-body ctxt #'rest)]
[(id* ...) (enumerate #'(rec-field* ...) 0)]
[rtd #'(type-descriptor rec-name)])
#'(if (#%$record/rtd? v rtd)
(let ([rec-field* (#%$record-ref v id*)] ...)
b b* ...)
altern))]))
(syntax-case x ()
[(_ expr cls* ...)
(with-syntax ([body (generate-body #'_ #'(cls* ...))])
#'(let ([v expr]) body))])))
;;;
(define-record constant (val))
(define (mkconst v) (make-constant v))
(define-record int (val))
(define (mkint v) (make-int v))
(define-record set (lhs rhs))
(define (mkset x v) (make-set x v))
(define-record reg (name))
(define (mkreg x) (make-reg x))
(define-record primcall (op rand*))
(define (mkprm op . rand*) (make-primcall op rand*))
(define-record seq (e0 e1))
(define (mkseq e0 e1) (make-seq e0 e1))
;;;
(define (recordize x)
(define who 'recordize)
;;;
(define (E x r)
(cond
[(pair? x)
(case (car x)
[(quote) (mkconst (cadr x))]
[else (error who "invalid expression ~s" x)])]
[else (error who "invalid expression ~s" x)]))
;;;
(E x '()))
;;;
(define (specify-representation x)
(define who 'specify-representation)
;;;
(define fixnum-scale 4)
;;;
(define (immediate? c)
(or (fixnum? c)))
;;;
(define (immediate-rep c)
(cond
[(fixnum? c) (mkint (* c fixnum-scale))]
[else (error 'immediate-rep "invalid ~s" c)]))
;;;
(define (Tail x)
(record-case x
[(constant c)
(if (immediate? c)
(immediate-rep c)
x)]
[else (error who "invalid tail ~s" x)]))
;;;
(Tail x))
;;;
(define (impose-calling-convention x)
(define who 'impose-calling-convention)
;;;
(define rv-register (mkreg '%eax))
;;;
(define (Tail x)
(record-case x
[(constant c)
(mkseq (mkset rv-register x)
(mkprm 'return rv-register))]
[else (error who "invalid tail ~s" x)]))
;;;
(Tail x))
;;;
(define (linearize x)
(define who 'linearize)
;;;
(define (op x)
(record-case x
[(register r) r]
[(constant c) `(obj ,c)]
[(int i) `(int ,i)]
;;;
(define (Effect x ac)
(record-case x
[(seq e0 e1)
(Effect e0 (Effect e1 ac))]
[(set targ v)
(cons `(movl ,(op v) ,(op targ)) ac)]
[else (error who "invalid effect ~s" x)]))
;;;
(define (Tail x ac)
(record-case x
[(seq e0 e1)
(Effect e0 (Tail e1 ac))]
[(primcall op rands)
(case op
[(return)
(cons '(ret) ac)]
[else (error who "invalid tail prim ~s" op)])]
[else (error who "invalid tail ~s" x)]))
;;;
(list (Tail x '())))
;;;
(define (compile x)
(let* ([x (expand x)]
[x (recordize x)]
[x (specify-representation x)]
[x (impose-calling-convention x)]
[x* (linearize x)]
[code (car (#%list*->code*
(lambda (x) #f)
x*))])
((#%$code->closure code))))
(compile x))
(define-syntax add-tests-with-string-output
(syntax-rules (=>)
[(_ name [expr* => str*] ...)
(begin
(printf "SECTION ~a ...\n" 'name)
(let ([str str*]
[expr 'expr*])
(printf "testing ~s\n" expr)
(let ([r (with-output-to-string
(lambda ()
(write (racompile expr))
(newline)))])
(unless (string=? r str)
(error #f "expected ~s, got ~s\n" str r))))
...)]))
(load "tests/tests-1.1-req.scm")