116 lines
3.2 KiB
Text
116 lines
3.2 KiB
Text
;;; Simple arithmetic expression compiler for jas in jas.
|
|
;;;
|
|
;;; The compiler is defined in the function
|
|
;;; compile-expression
|
|
;;;
|
|
;;; use as (for instance)
|
|
;;; (compile-expression (quote (+ (* 2 (+ 1 3)) 1)))
|
|
;;;
|
|
;;; This will generate a standalone program called results.class
|
|
;;; Run the bytecode interpreter on it as:
|
|
;;;
|
|
;;; % java results
|
|
;;;
|
|
;;; which will print the result of the expression
|
|
|
|
(define compile-expression
|
|
(lambda (expr)
|
|
(real-compile-expression expr)
|
|
(dump-code)))
|
|
|
|
;; The fun part...
|
|
|
|
(define real-compile-expression
|
|
(lambda (expr)
|
|
(cond
|
|
|
|
((num? expr)
|
|
(compile-number expr))
|
|
|
|
(1 (progn
|
|
(real-compile-expression (get-op1 expr))
|
|
(real-compile-expression (get-op2 expr))
|
|
(compile-op (get-op expr))
|
|
(set! cur-stack-height (- cur-stack-height 1)))))))
|
|
|
|
;; Ah well. Back to boring bookkeeping.
|
|
|
|
|
|
(define compile-number
|
|
(lambda (num)
|
|
(append-insn (bipush num))
|
|
(set! cur-stack-height (+ 1 cur-stack-height))
|
|
(cond
|
|
((< max-stack-height cur-stack-height)
|
|
(set! max-stack-height cur-stack-height)))))
|
|
|
|
(define compile-op
|
|
(lambda (op)
|
|
(cond
|
|
((eq? op (quote +)) (append-insn (iadd)))
|
|
((eq? op (quote -)) (append-insn (isub)))
|
|
((eq? op (quote *)) (append-insn (imul)))
|
|
((eq? op (quote /)) (append-insn (idiv))))))
|
|
|
|
(define get-op1
|
|
(lambda (expr) (car (cdr expr))))
|
|
(define get-op2
|
|
(lambda (expr) (car (cdr (cdr expr)))))
|
|
(define get-op
|
|
(lambda (expr) (car expr)))
|
|
|
|
(define append-insn
|
|
(lambda (insn)
|
|
(jas-code-addinsn my-code insn)))
|
|
|
|
(define cur-stack-height 1)
|
|
(define max-stack-height 1)
|
|
|
|
(define my-code (make-code))
|
|
(define my-init-code (make-code))
|
|
|
|
; define the main() portion,
|
|
; and the call to print out the
|
|
; results.
|
|
(define append-sequence
|
|
(lambda (code-part insn-list)
|
|
(mapcar (lambda (insn) (jas-code-addinsn code-part insn))
|
|
insn-list)))
|
|
|
|
(append-sequence
|
|
my-init-code
|
|
(quote
|
|
((aload_0)
|
|
(invokenonvirtual (make-method-cpe "java/lang/Object" "<init>" "()V"))
|
|
(return))))
|
|
|
|
(define dump-code
|
|
(lambda ()
|
|
(define my-env (make-class-env))
|
|
(jas-class-setclass my-env (make-class-cpe "results"))
|
|
(jas-class-setsuperclass my-env (make-class-cpe "java/lang/Object"))
|
|
(jas-class-addmethod my-env acc-public "<init>" "()V" my-init-code ())
|
|
(append-sequence
|
|
my-code
|
|
(quote
|
|
((getstatic
|
|
(make-field-cpe "java/lang/System" "out" "Ljava/io/PrintStream;"))
|
|
(swap)
|
|
(invokevirtual (make-method-cpe
|
|
"java/io/PrintStream" "println" "(I)V"))
|
|
(return))))
|
|
(jas-code-stack-size my-code max-stack-height)
|
|
(jas-class-addmethod my-env
|
|
(| acc-public acc-static)
|
|
"main" "([Ljava/lang/String;)V" my-code ())
|
|
(jas-class-write my-env
|
|
(make-outputstream "results.class"))))
|
|
|
|
;;;
|
|
;;; example usage of compiler.
|
|
;;;
|
|
;;; run the compiled class with
|
|
;;; % java results
|
|
;;; to get the answer.
|
|
|
|
(compile-expression (quote (+ (* 2 (+ 1 3)) 1)))
|