ese-eval4 - ifzero (was 写経)
ifzeroを自前で追加してスタックの使われかたへの理解を深める。
@@ -24,6 +24,11 @@ (name . begin) (args . ,args))) +(define (make-ifzero . args) + `((type . symbol) + (name . ifzero) + (args . ,args))) + (define (make-func cont) `((type . func) (cont . ,cont))) @@ -40,6 +45,9 @@ (define (begin? exp) (eq? (assq-ref exp 'name) 'begin)) +(define (ifzero? exp) + (eq? (assq-ref exp 'name) 'ifzero)) + (define (ese-symbol? exp) (type-eq? exp 'symbol)) @@ -101,6 +109,29 @@ ((eq? func 'resume) resume))))) +(define (make-ifzero-cont row-args) + (let ((test '()) (result '())) + (lambda (func) +;; optimized +;; (define (invoke-proc) +;; (if (null? test) +;; (make-need-sub-exp (list-ref row-args 0)) +;; (make-tail (if (zero? test) (list-ref row-args 1) (list-ref row-args 2))))) + +;; not optimized + (define (invoke-proc) + (cond ((null? test) (make-need-sub-exp (list-ref row-args 0))) + ((null? result) (make-need-sub-exp (if (zero? test) (list-ref row-args 1) (list-ref row-args 2)))) + (else (make-int result)))) + (define (resume retval) + (cond ((null? test) (set! test retval)) + ((null? result) (set! result retval)))) + (cond ((eq? func 'invoke-proc) + invoke-proc) + ((eq? func 'resume) + resume))))) + + (define (ese-eval exp) (let ((stack (make-queue)) (ret '())) (queue-push! stack exp) @@ -114,6 +145,8 @@ (queue-push! stack (make-func (make-flatten-cont (assq-ref exp1 'args) (cut fold + 0 <>))))) ((and (ese-symbol? exp1) (begin? exp1)) (queue-push! stack (make-func (make-begin-cont (assq-ref exp1 'args))))) + ((and (ese-symbol? exp1) (ifzero? exp1)) + (queue-push! stack (make-func (make-ifzero-cont (assq-ref exp1 'args))))) ((func? exp1) (queue-push! stack exp1) (let ((res (((assq-ref exp1 'cont) 'invoke-proc)))) @@ -130,6 +163,7 @@ (loop (dump-queue stack) (queue-pop! stack)))))) (ese-eval (make-begin (make-begin (make-int 5) (make-begin (make-int 3) (make-int 10))) (make-int 12))) +(print (ese-eval (make-ifzero (make-add (make-int 1) (make-int -1)) (make-int 1) (make-int 2)))) ;; (test-start "ese-eval") ;; (test* "eval int" 10 (ese-eval (make-int 10)))